vaynedu / nginx-1.16.0

学习nginx架构设计与实现,翻译nginx的源码,写nginx的测试代码, 在issue中记录nginx的精妙设计及其常见问题https://github.com/vaynedu/nginx-1.16.0/issues 。 myexercise内存池、哈希表、链表、md5、crc测试代码,mymodule中有hello自定义模块代码。通过nginx将自己整个知识体系连接起来
https://github.com/vaynedu/nginx-1.16.0/issues
BSD 2-Clause "Simplified" License
12 stars 2 forks source link

nginx互斥锁是如何实现的? #50

Open vaynedu opened 5 years ago

vaynedu commented 5 years ago

nginx互斥锁有3中实现方式:自旋锁(原子操作)、文件锁、原子操作+信号量

一. 自旋锁(原子操作)

1. 如何判断当前操作系统是否支持原子操作?

volatile 关键字告诉C编译器不要优化,就看是否支持volatile关键字,如果不支持,nginx模拟实现支持,这个需要使用到内联汇编, 需要使用到asm 关键字

2.nginx的自旋锁如何实现?

a) 其实锁很简单,也很好理解,锁只是一种同步的方式,保证资源的安全访问。怎么可以做到这一点呢,多进程环境,大家去共享内存去获取这个变量,哪个进程获取到这个变量,就相当于谁有锁, 谁就有权利访问这个资源。 b) 自旋锁: 进程获取不到锁就一直循环等待,之道获取到锁为止。nginx在自旋锁中使用了PAUSE指令用来提升CPU的性能,节省电量。 c) 这部分代码比较简单,一目了然

二. 文件锁

1.文件锁的原理就是在磁盘上创建一个文件(操作系统创建一个文件描述符),然后多个进程竞争去获取这个文件的访问权限,因此同一时刻只有一个进程能够访问临界区。 2.文件锁创造一个文件之后,会直接删除这个文件,只是用其fd (内核的信息结构),后面通过fcntl函数设置fd的属性,控制加解锁。 3.效率低下,不建议使用

三、原子操作+信号量

支持信号量只会影响阻塞进程的ngx_shmtx_lock方法持有锁的方式。当不支持信号量,就是自旋锁,支持信号量时,ngx_shmtx_lock将spin指定的一段时间内自旋等待其他CPU释放锁,如果达到spin的上限还没有获得锁,那么将会sem_wait使得当前进程进入睡眠状态,等待其他进程释放锁内核唤醒这个进程。nginx在spin上限之后如果还获得不了锁,很可能强制获得锁。 反正nginx作为高性能服务器,容不得半点阻塞,否则的很多连接就饿死了。 目前不清楚nginx到底是什么强制获得锁呢?猜测是不是特别高的优先级。疑问 备注:信号量使用不好很可能导致进程睡眠 todo: 信号量现在基本没有怎么使用,对这个不怎么清楚。

个人觉得: 原子操作 + 信号量 和 自旋锁都可以吧, nginx自旋锁很适合这种简单的场景,表现应该不会比 原子操作 + 信号量 实现方式差(虽然说自旋锁会盲目的旋转等待)