nginx源码分析1———进程间的通信机制五(文件锁)
来源:互联网 发布:sql 用变量作为字段名 编辑:程序博客网 时间:2024/05/16 11:22
相关介绍
nginx主要通过fcntl函数提供了劝告性记录上锁。所以在后面会设置seek offset相关的参数,因为fcntl可以对文件的一段记录进行上锁,上锁的粒度可以更小,不过本文只需要文件加锁就可以了,上锁的话,分为读写锁,本文只用了完全互斥的写锁。
系统调用
调用该函数进行初始化#include <fcntl.h>int fcntl(int fd, int cmd, .../* struct flock *args */);
1,fd是程序需要提供的打开的文件的fd。
2,cmd是命令,分别为以下三个命令。
F_SETLK 获取读(F_RDLCK)或者写锁(F_WRLCK)或者释放锁(F_UNLCK),当无法完成时就返回EACCES或者EAGAIN
F_SETLKW F_SETLK和一样,只是会阻塞,直到获取为止
F_GETLK 检查由args指向的锁以确定是否有某个已存在的锁会妨碍将新锁授予进程。如果当前没有这样的锁存在,由args指向的flock结构的l_type将被置为F_UNLCK。否则这个已存在的锁的信息由args指向的结构体返回。(可以理解为获取信息时候使用)
3,args将由flock结构组成,在flock中介绍。
相关结构
从这个结构体看出,该方式可以用于更小粒度的记录加锁。
struct flock{ //指定加锁的类型(F_RDLCK, F_WRLCK, F_UNLCK) short l_type; //定义记录相对开始的位置方式(SEEK_SET, SEEK_CUR, SEEK_END) short l_whence; //开始的位置 off_t l_start; //加锁的记录长度 off_t l_len; pid_t l_pid;};
创建
创建文件锁即是创建文件fd。
ngx_int_tngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name){ //已存在 if (mtx->name) { if (ngx_strcmp(name, mtx->name) == 0) { mtx->name = name; return NGX_OK; } ngx_shmtx_destroy(mtx); } //创建文件fd,其实调用底层的open,参数的宏都用nginx封装的一下。用可读可写可创建的方式创建一个默认权限的文件 mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN,NGX_FILE_DEFAULT_ACCESS); //判断是否创建成功 if (mtx->fd == NGX_INVALID_FILE) { ngx_log_error(NGX_LOG_EMERG, ngx_cycle->log, ngx_errno,ngx_open_file_n " \"%s\" failed", name); return NGX_ERROR; } //unlink文件 if (ngx_delete_file(name) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,ngx_delete_file_n " \"%s\" failed", name); } mtx->name = name; return NGX_OK;}
看到这里,肯定又要问题来了。那就是unlink后,文件fd依旧为什么还可以用,不冲突吗,文件还存在吗?
1,unlink函数删除文件,并且减少一个链接数。如果链接数达到0并且没有任何进程打开该文件,该文件内容才被真正删除。
2,如果在unlilnk之前没有close,那么依旧可以访问文件内容。所以只是unlink了文件,文件的链接数为0,但是进程与文件还有访问关系,所以文件并没有被删除。
3,在调用close时,内核会检查打开该文件的进程数,如果此数为0,进一步检查文件的链接数,如果这个数也为0,那么就删除文件内容。
阻塞加锁
加锁是两部分代码,我拷贝在一起了,主要看第二段
voidngx_shmtx_lock(ngx_shmtx_t *mtx){ ngx_err_t err; //加锁,如果成功就直接返回 err = ngx_lock_fd(mtx->fd); if (err == 0) { return; } ngx_log_abort(err, ngx_lock_fd_n " %s failed", mtx->name);}ngx_err_tngx_lock_fd(ngx_fd_t fd){ struct flock fl; ngx_memzero(&fl, sizeof(struct flock)); //l_type设定为写锁,也就是互斥锁。 fl.l_type = F_WRLCK; //加锁相对位置是文件的起点 fl.l_whence = SEEK_SET; //加锁会进行阻塞 if (fcntl(fd, F_SETLKW, &fl) == -1) { return ngx_errno; } return 0;}
非阻塞加锁
ngx_uint_tngx_shmtx_trylock(ngx_shmtx_t *mtx){ ngx_err_t err; err = ngx_trylock_fd(mtx->fd); if (err == 0) { return 1; } if (err == NGX_EAGAIN) { return 0; } ngx_log_abort(err, ngx_trylock_fd_n " %s failed", mtx->name); return 0;}ngx_err_tngx_trylock_fd(ngx_fd_t fd){ struct flock fl; ngx_memzero(&fl, sizeof(struct flock)); //同上面的阻塞加锁 fl.l_type = F_WRLCK; //同上面的阻塞加锁 fl.l_whence = SEEK_SET; //使用非等待方式加锁 if (fcntl(fd, F_SETLK, &fl) == -1) { return ngx_errno; } return 0;}
解锁
ngx_err_tngx_unlock_fd(ngx_fd_t fd){ struct flock fl; ngx_memzero(&fl, sizeof(struct flock)); //type设置为解锁 fl.l_type = F_UNLCK; //同前几个 fl.l_whence = SEEK_SET; //解锁 if (fcntl(fd, F_SETLK, &fl) == -1) { return ngx_errno; } return 0;}
销毁
voidngx_shmtx_destroy(ngx_shmtx_t *mtx){ //关掉fd,也就是关掉程序与文件的连接 if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,ngx_close_file_n " \"%s\" failed", mtx->name); }}
总结
文件锁通过fcntl,这种是通过内核维护的,无论进程是否非亲缘,都可以使用它进行同步,当然nginx把它的宏放在else最后,说明nginx并不太希望使用它,而是把它当作一个替补方案。为什么这样,想必各位已经明白。
- nginx源码分析1———进程间的通信机制五(文件锁)
- nginx源码分析1———进程间的通信机制二(自旋锁)
- nginx源码分析1———进程间的通信机制一(信号量)
- nginx源码分析1———进程间的通信机制三(mmap)
- nginx进程间的通信机制源码分析(二)-------原子操作、自旋锁、文件锁
- nginx源码分析1———进程间的通信机制四(System V内存共享)
- nginx源码分析1———进程间的通信机制六(UNIX域协议)
- Nginx源码分析 ——Nginx的进程通信方式
- nginx源码学习——进程间通信机制
- nginx源码分析--进程间通信机制 & 同步机制
- nginx源码学习(五)进程间的通信
- nginx进程间的通信机制源码分析(一)----共享内存
- nginx源码分析--nginx进程间通信
- nginx源码分析--nginx进程间通信
- Nginx源码分析与实践---进程间通信机制(共享内存)
- Nginx源码分析与实践---进程间通信机制(套接字)
- Nginx源码分析-master和worker进程间的通信
- Nginx源码分析--master和worker进程间的通信
- IIS下安装PHP
- Android APK安装常见错误列表
- 链表操作
- [ios]the file couldn't be opened because you don't have permission to view it
- 格雷码 Gray
- nginx源码分析1———进程间的通信机制五(文件锁)
- 通过Mesos、Docker和Go,使用300行代码创建一个分布式系统
- spring读取配置文件
- YUV格式学习:YUV444转换RGB24
- js改变html的原有内容
- Ext通过按钮创建一个Window实例代码
- 微信公众号开发学习
- C++基础---浅层及深层拷贝构造函数
- 九度 题目1020:最小长方形