本文转自:http://blogold.chinaunix.net/u/22617/showart_215469.html
当两个进程都要读写一个文件的时候, 需要用读写锁。 代码:
//具体的细节和原理可以参阅 《unix advanced programming 》 里面 12章 高级I/O, 记录锁一节int lock_reg(int fd, int cmd, int type,off_t offset, int whence, off_t len){ struct flock lock; lock.l_type = type; lock.l_start = offset; lock.l_whence = whence; lock.l_len = len; return fcntl(fd,cmd,&lock);}#define read_lock(fd,offset,whence,len) / lock_reg(fd,F_SETLK, F_RDLCK,offset,whence,len)#define readw_lock(fd,offset,whence,len) / lock_reg(fd,F_SETLKW, F_RDLCK,offset,whence,len)#define write_lock(fd,offset,whence,len) / lock_reg(fd,F_SETLK, F_WRLCK,offset,whence,len)#define writew_lock(fd,offset,whence,len) / lock_reg(fd,F_SETLKW, F_WRLCK,offset,whence,len)#define un_lock(fd,offset,whence,len) / lock_reg(fd,F_SETLK, F_UNLCK,offset,whence,len)
例子:实现一个函数操作文件:
/** Read the @job_conf , search the entry same as @job , if yes , update the entry with @job otherwise append the @job at the end of the @job_conf flag : JOB_DEL : Delete the record in download_job.conf JOB_UPDATE: update the record with new DownloadConf structure return: 0:success 这里要用到writer lock ,表面上是读job_conf ,但是实际上读完之后,就要彻底更新job_conf,所以应视为写操作**/int UpdateJob(const DownloadJob *job ,int flag , const char *job_conf){ FILE *fp = NULL; FILE *fp_new = NULL; DownloadJob job_info ; DownloadJob *job_ptr = &job_info; int fd = 0; //ready update the JOB_CONF 's item fp = fopen(JOB_CONF,"r+"); //其实这里主要是读,但是为了实现独占,所以用r+,配合使用writew_lock()(它要求fd是写打开的) if(!fp) { if(flag != JOB_DEL) { fp = fopen(JOB_CONF,"w"); fd = fileno(fp); //lockf(fd,F_LOCK,0); writew_lock(fd,0,SEEK_SET,0); fwrite(job,sizeof(DownloadJob),1,fp); //lockf(fd,F_ULOCK,0); un_lock(fd,0,SEEK_SET,0); fclose(fp); } } else { char buf[128]; int isFound = 0; memset(buf,'/0',sizeof(buf)); fd = fileno(fp); //lockf(fd,F_LOCK,0); //jprintf(" ============================== in UpdateJob function ==============================/n"); //jprintf("UpdateJob is waiting for writer lock /n"); writew_lock(fd,0,SEEK_SET,0); //sleep(10); //这里仅仅给客户演示 读者写者锁确实奏效而已!测试表明,读写者锁效率非常高!bob 2006-5-4 18:04 //jprintf("UpdateJob has got the writer lock /n"); fp_new = fopen("/etc/job_tmp.conf","w") ; while(fread((void *)job_ptr,sizeof(DownloadJob),1,fp)) { //jprintf("in UpdateJob() , %s /n",job_ptr->fullpath_name); if(!strcmp(job_ptr->fullpath_name,job->fullpath_name)) { // jprintf("job_ptr->fullpath_name = %s , job->fullpath_name = %s/n",job_ptr->fullpath_name,job->fullpath_name); if(flag == JOB_DEL) continue; else {// jprintf("job_ptr size = %u/n",sizeof(*job_ptr));// jprintf("job size = %u/n",sizeof(*job));// jprintf("job->SambaFullPathName = %s/n",job->SambaFullPathName); *job_ptr = *job; //job_ptr = job; isFound = 1; } }// jprintf("job_ptr->SambaFullPathName = %s/n",job_ptr->SambaFullPathName); fwrite((void *)job_ptr,sizeof(DownloadJob),1,fp_new); } if(!isFound) //this record is new , I append it at the end of file { if(flag != JOB_DEL) fwrite((void *)job,sizeof(DownloadJob),1,fp_new); } //lockf(fd,F_ULOCK,0); fflush(fp_new); fclose(fp_new); sync(); snprintf(buf,sizeof(buf)-1,"cp -f /etc/job_tmp.conf %s",JOB_CONF); system(buf); unlink("/etc/job_tmp.conf"); un_lock(fd,0,SEEK_SET,0); fclose(fp); } sync(); return 0; }