swoole_lock类支持5种锁的类型:
文件锁 SWOOLE_FILELOCK读写锁 SWOOLE_RWLOCK旗子暗记量 SWOOLE_SEM互斥锁 SWOOLE_MUTEX自旋锁 SWOOLE_SPINLOCK创建这些锁的过程实在便是调用布局函数的过程,调用的形式如下:
创建这些锁的过程实在便是调用布局函数的过程,调用的形式如下:
swoole_lock->__construct(int $type, [string $lockfile])$type为锁的类型$lockfile,当类型为SWOOLE_FILELOCK时必须传入,指定文件锁的路径
下面我们先容下这个锁的实现
static PHP_METHOD(swoole_lock, __construct){ long type = SW_MUTEX; char filelock; zend_size_t filelock_len = 0; int ret; //解析输入参数,这里输入参数有2个,个中type表示锁的类型,其余个参数是文件锁时必须传入(表示文件锁对应的文件路径),其他锁时,不须要这个参数 if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, \公众|ls\公众, &type, &filelock, &filelock_len) == FAILURE) { RETURN_FALSE; } //从内存池申请锁工具空间,这里仅仅是申请锁空间 swLock lock = SwooleG.memory_pool->alloc(SwooleG.memory_pool, sizeof(swLock)); if (lock == NULL)//申请空间失落败 { zend_throw_exception(swoole_exception_class_entry_ptr, \"大众global memory allocation failure.\"大众, SW_ERROR_MALLOC_FAIL TSRMLS_CC); RETURN_FALSE; } switch(type)//按type遍历,创建锁工具 {#ifdef HAVE_RWLOCK case SW_RWLOCK://如果是读写锁 ret = swRWLock_create(lock, 1);//创建锁工具,类型为读写锁 break;#endif case SW_FILELOCK://如果是文件锁 if (filelock_len <= 0)//第二个参数有效性检讨 { zend_throw_exception(swoole_exception_class_entry_ptr, \"大众filelock requires file name of the lock.\公众, SW_ERROR_INVALID_PARAMS TSRMLS_CC); RETURN_FALSE; } int fd; if ((fd = open(filelock, O_RDWR | O_CREAT, 0666)) < 0) //调用linux函数open,打开文件(不存在则创建) { zend_throw_exception_ex(swoole_exception_class_entry_ptr, errno TSRMLS_CC, \"大众open file[%s] failed. Error: %s [%d]\公众, filelock, strerror(errno), errno); RETURN_FALSE; } ret = swFileLock_create(lock, fd);//创建锁工具,类型为文件锁 break; case SW_SEM: ret = swSem_create(lock, IPC_PRIVATE);//创建锁工具,类型为旗子暗记量 break;#ifdef HAVE_SPINLOCK case SW_SPINLOCK: ret = swSpinLock_create(lock, 1);//创建锁工具,类型为乐不雅观锁 break;#endif case SW_MUTEX: default: ret = swMutex_create(lock, 1);//创建锁工具,类型为互斥量 break; } if (ret < 0) { zend_throw_exception(swoole_exception_class_entry_ptr, \公众failed to create lock.\"大众, errno TSRMLS_CC); RETURN_FALSE; } swoole_set_object(getThis(), lock);//PHP侧的工具和swoole内部工具关联 RETURN_TRUE;}
以下分别先容下各个不同锁工具的创建过程。
1、读写锁
int swRWLock_create(swLock lock, int use_in_process){ int ret; bzero(lock, sizeof(swLock));//锁空间初始化 lock->type = SW_RWLOCK;//设置锁的类型为读写锁 pthread_rwlockattr_init(&lock->object.rwlock.attr);//linux函数,锁属性信息初始化 if (use_in_process == 1)//标记为在进程中利用,这里pthread开头的linux函数默认都是针对线程的 { //设置锁的属性信息,标记为在进程中利用 pthread_rwlockattr_setpshared(&lock->object.rwlock.attr, PTHREAD_PROCESS_SHARED); } if ((ret = pthread_rwlock_init(&lock->object.rwlock._lock, &lock->object.rwlock.attr)) < 0)//linux函数,锁信息初始化 { return SW_ERR; } / 设置锁的回调函数 / lock->lock_rd = swRWLock_lock_rd; lock->lock = swRWLock_lock_rw; lock->unlock = swRWLock_unlock; lock->trylock = swRWLock_trylock_rw; lock->trylock_rd = swRWLock_trylock_rd; lock->free = swRWLock_free; return SW_OK;}
2、文件锁。
int swFileLock_create(swLock lock, int fd){ bzero(lock, sizeof(swLock));//锁工具信息初始化 lock->type = SW_FILELOCK;//设置锁的类型为文件锁 / 设置锁的回调函数 / lock->object.filelock.fd = fd; lock->lock_rd = swFileLock_lock_rd; lock->lock = swFileLock_lock_rw; lock->trylock_rd = swFileLock_trylock_rd; lock->trylock = swFileLock_trylock_rw; lock->unlock = swFileLock_unlock; lock->free = swFileLock_free; return 0;}
3、旗子暗记量锁
int swSem_create(swLock lock, key_t key){ int ret; lock->type = SW_SEM;//设置锁类型为旗子暗记量锁 if ((ret = semget(key, 1, IPC_CREAT | 0666)) < 0)//创建旗子暗记量,这里设置的属性IPC_CREAT,这表示这种旗子暗记量只能用于有亲缘关系的进程间 { return SW_ERR; } if (semctl(ret, 0, SETVAL, 1) == -1)//设置旗子暗记量ret的值为1 { swWarn(\"大众semctl(SETVAL) failed\公众); return SW_ERR; } lock->object.sem.semid = ret;//设置旗子暗记量ID / 设置回调函数 / lock->lock = swSem_lock; lock->unlock = swSem_unlock; lock->free = swSem_free; return SW_OK;}
4、乐不雅观锁
int swSpinLock_create(swLock lock, int use_in_process){ int ret; bzero(lock, sizeof(swLock));//初始化锁工具 lock->type = SW_SPINLOCK;//设置锁的类型为乐不雅观锁 //实行锁的初始化操作,这里指明是在多进程中利用 if ((ret = pthread_spin_init(&lock->object.spinlock.lock_t, use_in_process)) < 0) { return -1; } / 设置回调函数信息 / lock->lock = swSpinLock_lock; lock->unlock = swSpinLock_unlock; lock->trylock = swSpinLock_trylock; lock->free = swSpinLock_free; return 0;}
5、互斥量锁
int swMutex_create(swLock lock, int use_in_process){ int ret; bzero(lock, sizeof(swLock)); lock->type = SW_MUTEX; pthread_mutexattr_init(&lock->object.mutex.attr); if (use_in_process == 1) { pthread_mutexattr_setpshared(&lock->object.mutex.attr, PTHREAD_PROCESS_SHARED); } if ((ret = pthread_mutex_init(&lock->object.mutex._lock, &lock->object.mutex.attr)) < 0) { return SW_ERR; } lock->lock = swMutex_lock; lock->unlock = swMutex_unlock; lock->trylock = swMutex_trylock; lock->free = swMutex_free; return SW_OK;}