文件锁sysrepo笔记5

背景

sysrepo是基于共享内存的数据库,实际共享内存的外在体现是一个共享的文件。对这个共享文件的访问控制又是通过文件锁的方式来实现的。因为sysrepo只是一个库而已,会被多个进程链接,共享内存文件的路径都是一致的,在编译的时候确定了的。多进程间的资源互斥这里使用的就是文件锁的方式。

实现

sysrepo对数据的存储主要分为两块,一个是mainshm,用来保存概要的数据sr_main_shm_t和模块的信息数组sr_mod_t(大部分保存模块对应信息的一个偏移)。另一个是extshm,用来保存具体的模块对应的数据信息。

其中对mainshm的资源资源控制使用的是一个sr_main的文件锁来保护。同样的,对extshm的资源资源控制使用的是一个sr_ext的文件锁来保护。

今天主要介绍一下mainshm的文件锁sr_main的控制。

接口

涉及的锁接口主要有三个:

1/**2*

briefCreatemainSHMfilelockusedforcreatingmainSHM.3*4*

param[out]shm_lockSHMcreatelockfiledescriptor.5*

returnerr_info,NULLonsuccess.6*/7sr_error_info_t*sr_shmmain_createlock_open(int*shm_lock);89/**10*

briefLockmainSHMfilelock.Notethattheoldeststandardfilelocks11*areused,whichlockforthewholeprocess(everythread).12*13*

param[in]shm_lockOpenedSHMcreatelockfiledescriptor.14*

returnerr_info,NULLonsuccess.15*/16sr_error_info_t*sr_shmmain_createlock(intshm_lock);/**19*

briefUnlockmainSHMfilelock.20*21*

param[in]shm_lockLockedSHMcreatelockfiledescriptor.22*/23voidsr_shmmain_createunlock(intshm_lock);

这里shm_lock实际上是锁文件的文件描述符fd。

锁文件创建

1sr_error_info_t*2sr_shmmain_createlock_open(int*shm_lock)3{4sr_error_info_t*err_info=NULL;5char*path;6mode_tum;78if(asprintf(path,"%s/%s",sr_get_repo_path(),SR_MAIN_SHM_LOCK)==-1){9SR_ERRINFO_MEM(err_info);10returnerr_info;11}/*setumasksothatthecorrectpermissionsarereallyset*/14um=umask(SR_UMASK);*shm_lock=open(path,O_RDWR

O_CREAT,SR_MAIN_SHM_PERM);17free(path);18umask(um);19if(*shm_lock==-1){20SR_ERRINFO_SYSERRNO(err_info,"open");21returnerr_info;22}returnNULL;25}

这里获取到文件的路径,设置创建文件属性的掩码,然后使用open打开文件,如果文件不存在,创建文件并使用指定的访问属性。

加锁操作

1sr_error_info_t*2sr_shmmain_createlock(intshm_lock)3{4structflockfl;5intret;6sr_error_info_t*err_info=NULL;78assert(shm_lock-1);memset(fl,0,sizeoffl);11fl.l_type=F_WRLCK;12do{13ret=fcntl(shm_lock,F_SETLKW,fl);14}while((ret==-1)(errno==EINTR));15if(ret==-1){16SR_ERRINFO_SYSERRNO(err_info,"fcntl");17returnerr_info;18}returnNULL;21}

对文件加解锁使用了一个结构体structflock,定义一些文件的锁的选项。还有fcntl这个函数来设置定义的选项。

1intfcntl(intfiledes,intcmd,.../*structflock*flockptr*/);

这是一个拥有可变参数的函数声明,filedes自然是要操作的文件描述符,对与记录锁相关的操作,cmd只能是F_GETLK,F_SETLK,或者F_SETLKW,而第三个参数则必须是一个指向flock结构体的指针。

1structflock{2shortl_type;/*F_RDLCK,F_WRLCK,orF_UNLCK*/3off_tl_start;/*offsetinbytes,relativetol_whence*/4shortl_whence;/*SEEK_SET,SEEK_CUR,orSEEK_END*/5off_tl_len;/*length,inbytes;0meanslocktoEOF*/6pid_tl_pid;/*returnedwithF_GETLK*/7};

第一个成员是加锁的类型:只读锁,读写锁,或是解锁。l_start和l_whence用来指明加锁部分的开始位置,l_len是加锁的长度,l_pid是加锁进程的进程id。比如说,我们现在需要把一个文件的前三个字节加读锁,则该结构体的l_type=F_RDLCK,l_start=0,l_whence=SEEK_SET,l_len=3,l_pid不需要指定,然后调用fcntl函数时,cmd参数使用F_SETLK.

回到sr_shmmain_createlock函数,设置了读写锁类型F_WRLCK,cmd为F_SETLKW,然后就调用fcntl加锁了。

解锁操作

1void2sr_shmmain_createunlock(intshm_lock)3{4structflockfl;56memset(fl,0,sizeoffl);7fl.l_type=F_UNLCK;8if(fcntl(shm_lock,F_SETLK,fl)==-1){9assert(0);10}11}

这里设置cmd为F_SETLK,l_type类型为解锁。

demo编程

我写了一个demo程序,2个程序分别往一个共享内存写数据,对一个数进行累加。一个步进1,加10次。一个步进2,加10次。当两个程序结束后,都延迟10s钟,分别再读取数据,最终的结果应该是我们认为的30。

文件锁

demo代码路径:



转载请注明地址:http://www.shiquanren.net/hzzz/hzzz/26618.html


  • 上一篇文章:
  • 下一篇文章: 没有了
  • 公司简介 广告合作 发布优势 服务条款 隐私保护 网站地图 版权声明