voidmy_lock(intfd)
{
structflocklock;
lock.l_type=F_WRLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=0;/**//*writelockentirefile*/
Fcntl(fd,F_SETLKW,&lock);
}
voidmy_unlock(intfd)
{
structflocklock;
lock.l_type=F_UNLCK;
lock.l_whence=SEEK_SET;
lock.l_start=0;
lock.l_len=0;/**//*unlockentirefile*/
Fcntl(fd,F_SETLK,&lock);
}
staticvoidrwlock_cancelrdwait(void*arg)
{
pthread_rwlock_t*rw;
rw=arg;
rw->rw_nwaitreaders--;
pthread_mutex_unlock(&rw->rw_mutex);
}
/**//*endrwlock_cancelrdwait*/
intpthread_rwlock_rdlock(pthread_rwlock_t*rw)
{
intresult;
if(rw->rw_magic!=RW_MAGIC)
return(EINVAL);
if((result=pthread_mutex_lock(&rw->rw_mutex))!=0)
return(result);
/**//*4givepreferencetowaitingwriters*/
while(rw->rw_refcount<0||rw->rw_nwaitwriters>0){
rw->rw_nwaitreaders++;
pthread_cleanup_push(rwlock_cancelrdwait,(void*)rw);
result=pthread_cond_wait(&rw->rw_condreaders,&rw->rw_mutex);
pthread_cleanup_pop(0);
rw->rw_nwaitreaders--;
if(result!=0)
break;
}
if(result==0)
rw->rw_refcount++;/**//*anotherreaderhasareadlock*/
pthread_mutex_unlock(&rw->rw_mutex);
return(0);
}
staticvoidrwlock_cancelwrwait(void*arg)
{
pthread_rwlock_t*rw;
rw=arg;
rw->rw_nwaitwriters--;
pthread_mutex_unlock(&rw->rw_mutex);
}
/**//*endrwlock_cancelwrwait*/
intpthread_rwlock_wrlock(pthread_rwlock_t*rw)
{
intresult;
if(rw->rw_magic!=RW_MAGIC)
return(EINVAL);
if((result=pthread_mutex_lock(&rw->rw_mutex))==-1)
return(result);
while(rw->rw_refcount!=0){
rw->rw_nwaitwriters++;
pthread_cleanup_push(rwlock_cancelwrwait,(void*)rw);
result=pthread_cond_wait(&rw->rw_condwriters,&rw->rw_mutex);
pthread_cleanup_pop(0);
rw->rw_nwaitwriters--;
if(result!=0)
break;
}
if(result==0)
rw->rw_refcount=-1;
pthread_mutex_unlock(&rw->rw_mutex);
return(0);
}
如果想让进程只有一个拷贝运行,可以维护一个文件,在进程运行时先对其记录上写锁,则其他拷贝就无法获取到写锁,也就无法运行其他拷贝。
<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
#include"unpipc.h"
#definePATH_PIDFILE"pidfile"
intmain(intargc,char**argv)
{
intpidfd;
charline[MAXLINE];
/**//*4openthePIDfile,createifnonexistent*/
pidfd=Open(PATH_PIDFILE,O_RDWR|O_CREAT,FILE_MODE);
/**//*4trytowritelocktheentirefile*/
if(write_lock(pidfd,0,SEEK_SET,0)<0){
if(errno==EACCES||errno==EAGAIN)
err_quit("unabletolock%s,is%salreadyrunning?",
PATH_PIDFILE,argv[0]);
else
err_sys("unabletolock%s",PATH_PIDFILE);
}
/**//*4writemyPID,leavefileopentoholdthewritelock*/
snprintf(line,sizeof(line),"%ld/n",(long)getpid());
Ftruncate(pidfd,0);
Write(pidfd,line,strlen(line));
/**//*thendowhateverthedaemondoes*/
pause();
}
当然一个守护进程防止自身另一个拷贝的启动还有其他方法,比如可以使用信号灯。
若以O_CREATE和O_EXCL来调用open函数,则若文件存在,就返回一个错误,我们可以用这个技巧来将文件作为锁用。
#include"unpipc.h"
#defineLOCKFILE"/tmp/seqno.lock"
voidmy_lock(intfd)
{
inttempfd;
while((tempfd=open(LOCKFILE,O_RDWR|O_CREAT|O_EXCL,FILE_MODE))<0){
if(errno!=EEXIST)
err_sys("openerrorforlockfile");
/**//*someoneelsehasthelock,looparoundandtryagain*/
}
Close(tempfd);/**//*openedthefile,wehavethelock*/
}
voidmy_unlock(intfd)
{
Unlink(LOCKFILE);/**//*releaselockbyremovingfile*/
}
这种技巧有三个问题:
1,若持有该锁的进程没有释放锁就终止了,则此文件名没有被删除,对于这个问有一些办法,比如检查文件的最近访问时间,若大于某个阀值,则认定它已经被遗忘了。另一个办法是把持有锁的进程ID写入锁文件中,则其他进程可以读出该进程ID,并去检查进程是否还在运行,但这也有问题,因为进程ID在过一段时间后是会重用的。但这些情形对于fcntl记录上锁来说都不成问题,因为进程终止时,它持有的记录锁都自动释放。
2,若已经有另外一个进程打开了锁文件,则当前进程只是在一个无限循环中不断调用open,也就是轮询。一个替代技巧是sleep一下,再尝试open.当然若使用fcntl进行记录上锁,这不成问题,只要想持有锁的进程指定FSETLKW命令,那么内核将把该进程投入睡眠,直到锁可用再唤醒它。
3,调用open和unlink创建和删除额外一个文件涉及文件系统的访问,这比调用fcntl两次(一个获取锁,一次释放锁)所花时间长得多。
互斥锁和信号量的区别是:互斥锁必须总是由锁住它的线程来解锁,但信号量的signal却不必由执行过它的wait操作的同一个线程来执行。
分享到:
相关推荐
unix网络编程卷2第二版英文版 unix网络编程卷2第二版英文版 unix网络编程卷2第二版英文版 unix网络编程卷2第二版英文版 unix网络编程卷2第二版英文版 unix网络编程卷2第二版英文版 unix网络编程卷2第二版英文版 unix...
UNIX网络编程卷1代码.rarUNIX网络编程卷1代码.rar
《UNIX网络编程》(第1卷)(套接口API第3版)第1版和第2版由已故UNIX网络专家W. Richard Stevens博士独自编写。《UNIX网络编程》(第1卷)(套接口API第3版)是3版,由世界著名网络专家Bill Fenner和Andrew M. Rudoff执笔,...
unix网络编程第2版(1 2卷).pdf UNIX网络编程卷1:套接字联网API(第3版).pdf UNIX网络编程 卷2:进程间通信(第2版).pdf 计算机网络(第七版)复习题答案与课本对应.doc 计算机网络(第7版)-谢希仁.pdf
卷2:进程间通信(第2版)》是一部UNIX网络编程的经典之作!进程间通信(IPC)几乎是所有Unix程序性能的关键,理解IPC也是理解如何开发不同主机间网络应用程序的必要条件。《UNIX网络编程.卷2:进程间通信(第2版)》从对...
unix网络编程卷2,介绍的内容很全面,很适合刚接触linux或者unix网络编程开发人员学习
UNIX环境高级编程高清版_PDF版 + UNIX网络编程卷1高清版_PDF版
UNIX网络编程 卷2
unix网络编程-第三版读书笔记unix网络编程-第三版读书笔记
笔记_UNIX环境网络编程卷二进程间通信_中文第二版
unix网络编程读书笔记unix网络编程读书笔记unix网络编程读书笔记unix网络编程读书笔记unix网络编程读书笔记
《LINUX与UNIX SHELL编程指南》读书笔记-二次发布版
UNIX 网络编程卷 2 进程间通信读书笔记(一)
《UNIX网络编程 卷1:套接字联网API(第2版)》是一部UNIX网络编程的经典之作。书中全面深入地介绍了如何使用套接字API进行网络编程。全书不但介绍了基本编程内容,还涵盖了与套接字编程相关的高级主题,对于客户/...
( UNIX网络编程 卷2:进程间通信(第2版)中文PDF版,网络编程基础
UNIX网络编程卷1(第三版 英文版).pdf
改资源是zip压缩包,里面包括: UNIX网络编程(第2版)卷1:套接口API和XOpen.传输接口API.pdf UNIX网络编程(第2版)卷2:进程间通信.pdf
UNIX网络编程 卷2:进程间通信(第2版)PDF 及 源代码; PDF 是中文扫描版的; 源代码里面有 .tar.gz 【在MAC/Linux/Unix 环境下使用 “tar zxvf xxx.tar.gz”解压】 以及 .zip 两种格式的文件【它们内容是一样的】...
UNIX网络编程随书源代码(包含卷一卷二)