广州市规划建设局网站,网站建设费是什么,全网推广服务,网站设计相似侵权吗读写锁 当一个进程正在读或者修改某个文件的某个部分时#xff0c;组织其他进程修改同一个文件或者同一个文件的某个区域。对于Linux来说一切皆是文件#xff0c;包括IO设备共享内存#xff1b; 接口 int fcntl(int fd, int cmd, struct flock *lock)#xff1b;表示锁操作… 读写锁 当一个进程正在读或者修改某个文件的某个部分时组织其他进程修改同一个文件或者同一个文件的某个区域。对于Linux来说一切皆是文件包括IO设备共享内存 接口 int fcntl(int fd, int cmd, struct flock *lock)表示锁操作fd表示文件描述符cmd表示命令F_GETLK表示获取锁设置锁F_SETLK用于加解锁F_SETLKW用于设置加解阻塞锁 struct flock { i_type //F_RDLCK表示读取锁读取锁是共享锁F_WRLCK是写入锁写入锁是排它锁F_UNLCK表示用于解锁 I_whence //SEEK_SET:表示在文件的开头为锁定的起始位置SEEK_CUR表示以目前读写位置为锁定的起始位置SEEK_END表示以文件的结尾为锁定的起始位置 I_start //表示相对于I_whence位置的偏移量 I_len //表示锁定区域的长度0表示全文 I_pid //当前占用锁的的PID只对F_GETLK命令有效 }; 返回值-1表示失败0表示SET命令设置成功 记录锁获取锁信息fcntl(fd,F_GETLK)设置锁fcntl(fd,F_SETLK,arg)fcntl(fd,F_SETLKW,arg); file_wrlock.c #include #include #include #include #include int fd; void handler(int sig){ struct flock lock; lock.l_type F_UNLCK; lock.l_whence SEEK_SET; lock.l_start 0; lock.l_len 0; if(-1 fcntl(fd,F_SETLKW,lock)){ perror(fcntl error); exit(1); } } int main(int argc, char* argv[]){ signal(SIGUSR1,handler); int c,start 0,len 0; while((c getopt(argc,argv,s:l:))!-1){ switch(c){ case s: start atoi(optarg); break; case l: len atoi(optarg); break; } } if(optind ! argc -1){ printf(usage:%s [-s ] [-l ] \n,argv[0]); return 1; } fd open(argv[optind],O_WRONLY); if(-1 fd){ perror(open error); return 1; } struct flock lock; lock.l_type F_WRLCK; lock.l_whence SEEK_SET; lock.l_start start; lock.l_len len; if(-1 fcntl(fd,F_SETLKW,lock)){ perror(fcntl error); return 1; } pause(); for(;;); close(fd); } 文件读锁 file_rdlock.c #include #include int main(int argc, char* argv[]){ if(2!argc){ printf(usage:%s \n,argv[0]); return 1; } int fd open(argv[1],O_RDONLY); if(-1 fd){ perror(open error); return 1; } struct flock lock; lock.l_type F_RDLCK; lock.l_whence SEEK_SET; lock.l_start 0; lock.l_len 0; if(-1 fcntl(fd,F_SETLK,lock)){ perror(fcntl error); return 1; } pause(); close(fd); } view_lock.c用于查看锁的状态但是一般只能用于查看写锁的状态不能够查看读锁的状态 #include #include #include int main(int argc, char* argv[]){ if(2!argc){ printf(usage:%s \n,argv[0]); return 1; } int fd open(argv[1],O_RDWR); if(-1 fd){ perror(open error); return 1; } struct flock lock; bzero(lock,sizeof(lock)); if(-1 fcntl(fd,F_GETLK,lock)){ perror(fcntl error); return 1; } printf(file:%s,lock type:%d,start:%d,len:%d,by %d\n,argv[1],lock.l_type,lock.l_start,lock.l_len,lock.l_pid); } file_unlock.c用于解除锁解锁操作只能在本进程完成否则解锁操作就会失败 #include #include int main(int argc, char* argv[]){ if(2!argc){ printf(usage:%s \n,argv[0]); return 1; } int fd open(argv[1],O_WRONLY); if(-1 fd){ perror(open error); return 1; } struct flock lock; lock.l_type F_UNLCK; lock.l_whence SEEK_SET; lock.l_start 0; lock.l_len 0; if(-1 fcntl(fd,F_SETLKW,lock)){ perror(fcntl error); return 1; } pause(); close(fd); } 读写锁的分类 访问操作同一个进程访问只会覆盖已有的锁锁包含写入锁(排它锁)读写锁(共享锁)加锁区域文件锁对于整个文件上锁记录锁对于文件的部分区域上锁 锁的实现方式 建议性锁(Advisory locking)别名 劝诫锁协作锁每个上锁的进程都需要检查是否有锁存在当然还需要尊重已有的锁这个规范需要程序员来实现 强制性锁(Mandatory locking)当文件悲伤所来进行写入操作时在锁定该文件的进程释放锁之前内核会阻止任何对该文件的读或者写的访问(open、read、write),每次读或者写访问之前都得检查锁是否存在但是缺点是内核实现系统开销很大并且系统之间的兼容性很差(Mac OS不支持强制性锁)本质是内核读写文件自动处理 设置mount -o remount,mand/nomand分别表示允许强制锁定禁止强制锁定写该文件权限chmod gsg-x来设置权限 进程死锁的情况 deadlock.c #include #include #include #include void lock(const char* pathname){ int fd open(pathname,O_WRONLY); if(-1 fd){ perror(open error); exit(1); } struct flock lock; lock.l_type F_WRLCK; lock.l_whence SEEK_SET; lock.l_start 0; lock.l_len 0; if(-1 fcntl(fd,F_SETLKW,lock)){ perror(fcntl error); exit(1); } //close(fd); } int main(int argc, char* argv[]){ if(3!argc){ printf(usage:%s \n,argv[0]); return 1; } printf(PID:%d lock file %s\n,getpid(),argv[1]); lock(argv[1]); printf(sleep 1s\n); sleep(1); printf(PID:%d lock file %s\n,getpid(),argv[2]); lock(argv[2]); pause(); } 补充一个关于lseek函数 lseek_append.c用于实现在文件的特定位置插入数据但是不进行覆盖操作 #include #include #include #include #include int main(int argc,char* argv[]){ if(4 ! argc){ printf(usage:%s \n,argv[0]); return 1; } int fd open(argv[1],O_RDWR); if(-1 fd){ return 1; } off_t off lseek(fd,atoi(argv[2]),SEEK_SET); if(-1 off){ return 1; } struct stat stat_buf; fstat(fd,stat_buf); size_t save_size stat_buf.st_size - off; //char buf[save_size]; char *buf malloc(save_size); if(-1 read(fd,buf,save_size)){ return 1; } off lseek(fd,atoi(argv[2]),SEEK_SET); if(-1 off){ return 1; } if(-1 write(fd,argv[3],strlen(argv[3]))){ return 1; } if(-1 write(fd,buf,save_size)){ return 1; } free(buf); buf NULL; } lseek_write.c用于执行在特定的位置写入数据的功能 #include #include #include #include #include int main(int argc,char* argv[]){ if(4 ! argc){ printf(usage:%s \n,argv[0]); return 1; } int fd open(argv[1],O_WRONLY); if(-1 fd){ return 1; } off_t off lseek(fd,atoi(argv[2]),SEEK_SET); if(-1 off){ return 1; } if(-1 write(fd,argv[3],strlen(argv[3]))){ return 1; } } lseek_read.c用于在特定的位置进行数据的读取功能 #include #include #include #include #include int main(int argc,char* argv[]){ if(4 ! argc){ printf(usage:%s \n,argv[0]); return 1; } int fd open(argv[1],O_RDONLY); if(-1 fd){ return 1; } off_t off lseek(fd,atoi(argv[2]),SEEK_SET); if(-1 off){ return 1; } size_t len atoi(argv[3]); char buf[len1]; bzero(buf,len1); if(-1 read(fd,buf,len)){ return 1; } printf(%s\n,buf); }