Chinaunix首页 | 论坛 | 博客

fx

  • 博客访问: 1372488
  • 博文数量: 115
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 3964
  • 用 户 组: 普通用户
  • 注册时间: 2013-05-02 14:36
文章分类
文章存档

2022年(2)

2019年(2)

2018年(10)

2017年(1)

2016年(50)

2015年(12)

2014年(9)

2013年(29)

分类: C/C++

2013-05-05 16:37:31

在介绍open函数时,我们详细介绍过O_EXCL标志的作用。
它和O_CREAT一起作用时,就会先测试需要创建的文件在不在,不在就会创建
该文件。如果存在,就出错返回。
但这里的测试和出错是一个原子操作。
什么意思呢,就是说测试和创建是一个不可分割的步骤,他们要么都不执行,
要么就都执行。不会发生测试完后,cpu切换到另一个进程的情况。
那如果没有这O_EXCL标志我们会怎么做呢。
我们可能会编写下面这样的程序:
if((fd=open(pathname,O_WRONLY))==-1){
if(ENOENT==errno){
if((fd=crear(pathname,mode))==-1){
perror("creat error");
exit(1);
}else{
perror("open error");
exit(1);
}
}
}


现在如果a进程在执行这段当执行完open时发现没有这个文件(因为没有指定O_CREAT这个标志)
那么open出错返回,errno被设置成ENOENT,在执行creat前,cpu切换到了另一个进程 B 执行,假如这个时候进程
B 创建了这个文件。并写入了部分数据。然后cpu又切换到A进程去执行。然后A接着调用creat函数。
这时候就会清空这个文件的内容(creat调用相当于open(pathname,O_WRONLY | O_CREAT | O_TRUNC,mode))
那么B进程写入的数据就会丢失。
问题就是出在了 对文件存在与否的测试和不存在就创建文件 是两个函数完成的,而任何一个需要两个分开的函数调用
的操作都不可能是原子操作,因为在这两个函数调用之间,内核有可能挂起改进程而去执行别的进程。就像
上面做的那样。



那么如果我们需要再一个文件的某个任意位置出开始(读)写数据。那么我们就需要两个操作一个是定位操作,然后是
(读)写数据操作。
XSI扩展中定义了两个可以原子 定位读写的 函数
ssize_t pread(int fileds, void *buf ,sizt_t nbutes,off_t offset);
ssize_t pwrite(int filedes,void *buf,size_t nbytes,off_t offset);


这里除了他们是原子操作外还有一点需要注意  pread()不更新文件指针
什么意思呢,我们写一段测试代码看看就知道了
我们创建了一个文件test 内容为“123456789”


a程序先先练两次调用read(),每次读取三个字节
b程序先调用pread()在离文件头五个字节出读3数据,然后在调用read()读取三个字节。




a程序为:
 
 9 fd=open("test",O_RDONLY);
 10         read(fd,buf,3);
 11         buf[3]='\0';
 12         printf("%s\n",buf);
 13         read(fd,buf,3);
 14         buf[3]='\0';
 15         printf("%s\n",buf);


输出为:
123
456


b程序为


 9 fd=open("test",O_RDONLY);
 10         pread(fd,buf,3,5);
 11         buf[3]='\0';
 12         printf("%s\n",buf);
 13         read(fd,buf,3);
 14         buf[3]='\0';
 15         printf("%s\n",buf);
输出为:
678
123


从输出我们可以很清楚的看出。pread()调用并不会改变文件指针。上面b程序中pread读取三个数据后
你可能会觉得文件当前偏移量变成8了 后面的read调用会从9开始读。但是pread实际上是不会改变文件指针
所以后面的read会从文件头开始读取。
而read调用会改变文件指针,所以a程序中第二次read调用会从第一次读完的地方接着读。

阅读(8009) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~