linux基础之文件锁,读写锁相关
来源:互联网 发布:迅雷校园招聘java笔试 编辑:程序博客网 时间:2024/06/05 03:16
在看建议锁和强制锁时看到的一个帖子。主要问题是,程序运行理想效果是通过创建99个子进程,写入文本100*1000个数。但运行时会随机的少写十几个二十个数。源码如下:
#include <stdio.h>#include <fcntl.h>int main(){struct flock stF;int i,n,fd,pid;fd=open("./output.txt",O_RDWR|O_CREAT);for(i=0;i<99;i++){ pid=fork(); if(pid==-1) { perror("fork:"); } else if( pid > 0 ) { break; }}stF.l_type=F_WRLCK;stF.l_start=0;stF.l_whence=SEEK_SET;stF.l_len=0;for(i=0;i<999;i++){ if(fcntl(fd,F_SETLKW,&stF)==-1) { perror("lock:"); } lseek(fd,0,SEEK_END); if(write(fd,"1",1)!=1) { perror("write:"); } stF.l_type=F_UNLCK; if(fcntl(fd,F_SETLKW,&stF)==-1) { perror("unlock:"); }}close(fd);}
在查看每次写入数据和pid时,发现数据都会出错。应该是lseek()与fcntl()之间的,还有锁的问题。
很简单,问题在于进程调度,多进程写入同一个文件时存在竞争条件,而lseek和write组合在一起不是原子操作
问题代码:
lseek(fd,0,SEEK_END); // 如果系统刚好把进程挂起在这里,下次进程调度重新运行时将覆盖掉其它进程在此期间向文件写入的数据
if(write(fd,"1",1)!=1)
解决办法很简单,不用lseek调用,直接
lseek(fd,0,SEEK_END); // 如果系统刚好把进程挂起在这里,下次进程调度重新运行时将覆盖掉其它进程在此期间向文件写入的数据
if(write(fd,"1",1)!=1)
解决办法很简单,不用lseek调用,直接
fd = open("./output.txt", O_RDWR | O_CREAT | O_APPEND)
具体原因希望有大侠能解惑啊。对内核运行什么的还不是很了解。
修改方法有如下两种:
一:在打开文件时设置为在每次写之前,都讲标志位移动到文件的末端,而不用lseek()
#include <stdio.h>#include <fcntl.h>#include <sys/stat.h>#include <sys/types.h>int main(){struct flock stF;struct stat stat;int i,n,fd,pid;//fd=open("./output.txt",O_RDWR|O_CREAT);fd=open("./output.txt",O_RDWR|O_CREAT|O_APPEND);for(i=0;i<99;i++){ pid=fork(); if(pid==-1) { perror("fork:"); } else if( pid > 0 ) { break; }}stF.l_type=F_WRLCK;stF.l_start=0;stF.l_whence=SEEK_SET;stF.l_len=0;for(i=0;i<1000;i++){ if(fcntl(fd,F_SETLKW,&stF)==-1) { perror("lock:"); }//lseek(fd,0,SEEK_END); if(write(fd,"1",1)!=1) { perror("write:"); } fstat(fd, &stat); printf("%d\n", (int)stat.st_size); stF.l_type=F_UNLCK; if(fcntl(fd,F_SETLKW,&stF)==-1) { perror("unlock:"); }}close(fd);}
二:不是写一次数就解锁一次,而是每个进程写完后,解锁让其他进程继续操作。这种也不会出错。缺点是:其实整体看,其实是多个进程排序执行,实时效果不好。
#include <stdio.h>#include <fcntl.h>int main(){struct flock stF;int i,n,fd,pid;fd=open("./output.txt",O_RDWR|O_CREAT);for(i=0;i<99;i++){pid=fork();if(pid==-1){ perror("fork:");}else if( pid > 0 ){ break;}}stF.l_type=F_WRLCK;stF.l_start=0;stF.l_whence=SEEK_SET;stF.l_len=0;for(i=0;i<1000;i++){if(fcntl(fd,F_SETLKW,&stF)==-1){ perror("lock:");}lseek(fd,0,SEEK_END);if(write(fd,"1",1)!=1){ perror("write:");}}stF.l_type=F_UNLCK;if(fcntl(fd,F_SETLKW,&stF)==-1){perror("unlock:");}close(pid);close(fd);}
- linux基础之文件锁,读写锁相关
- Linux基础之文件读写流程
- iOS基础之文件读写
- linux爱好者之基础篇--文件相关命令
- LInux基础之目录、文件相关知识总结
- linux之读写锁技术
- linux多线程之读写锁
- linux多线程之读写锁
- linux文件读写 文件锁、select、poll
- Linux 多进程读写文件 文件锁
- linux文件读写 文件锁、select、poll .
- Linux 多进程读写文件 文件锁
- linux文件读写 文件锁、select、poll
- linux学习之读写文件
- Linux之文件读写过程
- java多线程读写文件之文件锁
- 【Linux基础】文件相关命令
- Java语言基础之文件读写
- maximo 日期格式调整
- SNS社交平台的核心技术架构
- (swing读书笔记)JTable简介(上)
- SQL ERROR 17002
- (swing读书笔记)JTable简介(中)
- linux基础之文件锁,读写锁相关
- 关于bcb6.0编译错误:[Linker Fatal Error] Fatal: Illegal option
- (swing读书笔记)JTable简介(下)
- const常用小结
- 共享内存区
- (swing读书笔记)JTree简介(上)
- C基础
- <<春·加薪>>
- ksoftirqd内核线程