Chinaunix首页 | 论坛 | 博客

fx

  • 博客访问: 1372503
  • 博文数量: 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-04 23:25:59

#include

int open(const char *pathname,int oflag,..../*mode_t mode*/)
                                            返回值:成功则返回文件描述符,若出错则返回-1

调用open函数可以打开或创建一个文件。第三个参数写为...,对open函数而言,仅当创建新文件时才使用第三个参数.
pathname是要打开或创建文件的名字,oflag参数可用来说明此函数的多个选项下面我们逐个讲解各个 标志 的作用

O_RDONLY  :只读打开,使用此标志打开的文件只能读取数据。

O_WRONLY: 只写打开,使用此标志打开的文件只能往文件中写数据而不能读数据。

O_RDWR:
以读写方式打开文件。
上面这三个标志必须而且指定一个且只能指定一个
O_APPEND每次写时都追加到文件尾端(open函数打开文件时当前文件偏移量默认是指向文件头处的),当指定这个标志是,打开文
件是当前文件偏移量指向文件结尾处,之后的写操作将从文件尾端开始写。我们写个测试的例子
我们创建个临时文件test内容是 aaaaaaa 然后我们以读写方式打开改文件之后写入bbb到文件中。然后查看文件内容
之后我们再把文件内容回复为   aaaaaaa 然后我们以o_append 和读写方式打开文件后写入bbb然后 再查看文件内容
 
文件test的内容为aaaaaaa
7         fd=open("test",O_RDWR);

9         char buf[20]="bbb";
10        write(fd,buf,3);

我们 查看test文件内容为:
  1 bbbaaaa

现在我们回复文件test内容为 aaaaaaa  并添加o_append标志
  7         fd=open("test",O_RDWR | O_APPEND);
  8 
  9         char buf[20]="bbb";
 10         write(fd,buf,3);

查看文件test内容为:
  1 aaaaaaa
  2 bbb

o_creat:若设置了此标志文件,不存在该文件时会创建此文件。(若该文件已经存在,那么此标志不起作用)使用此选项时,需要

第三个参数mode。用来指定该新文件的访问权限
文件访问权限如下:S_IRUSR(用户-读) S_IWUSR(用户-写) S_IXUSR(用户-执行) 
                 S_IRGRP(组-读) S_IWGRP(组-写)   S_IXGRP(组-执行)
                 S_IROTH(其他-读)S_IWOTH(其他-写) S_IXOTH(其他-执行)
这里需要注意:使用o_creat标志创建文件是,创建出来的文件的权限是 指定的文件权限减去umask指定的屏蔽字后剩下的 文件权限。

O_TRUNC:如果指定了这个标志,则将文件长度截断为0,文件当前偏移量指向文件头。前面说过没有这些标志时,打开文件的文件当前偏移量默认指向文件头。既然默认
打开时文件偏移量指向文件头,那么为什么还要o_trunc这个标志呢。 前面我们做过测试 
对文件 test(内容为aaaaaaa)不指定额外的标志打开文件的情况下写“bbb"到文件时  文件内容为"bbbaaaa"  也就是文件内容不变,只是当前文件
偏移量指向文件头,然后开始写入数据,这就导致了写入的数据将原来的数据覆盖掉出现 "bbbaaaa" 的内容。
我们来看看指定了o_trunc标志后向文件 test(内容为'aaaaaaa')写入bbb 后文件的内容
  7         fd=open("test",O_RDWR | O_TRUNC);
  8         char buf[20]="bbb";
  9         write(fd,buf,3);
查看文件内容为:
  1 bbb

也就是说指定了o_trunc标志后。不仅文件test的文件当前偏移量被重置为指向文件头,文件的内容也被清空。

O_EXCL:如果同时指定了o_creat标志,而文件已经存在,则会出错。此标志可以测试一个文件是否存在,如果不存在,则创建测文件。
这使测试和创建文件两者成为一个原子操作(关于原子操作请参考 博客里另一篇文章 http://blog.chinaunix.net/uid-28852942-id-3652277.html)。
如果测试和创建文件成为一个原子操作,那么我们可以用他 简单模拟一下 互斥锁
    这里简单说名一下临界区,当两个进程都能够访问一块共享的内存时。那么对这个共享内存的访问就需要特别的操作。比如a进程在写这块内存时
如果这个写操作没有完成那么b进程就不能读也不能写这块内存。这块共享内存就是临界区,即对他的访问,同一时间只能有一个进程能够读写这块内存
 那么我们就能用指定了o_excl标志的open 来控制进程间对这个共享内存的互斥访问。
例如在每次 A 进程需要读写 这块共享内存时,就调用
指定了o_excl标志的open()函数。当该文件存在时那么 文件就不能创建,Open函数出错。我们就知道已经有一个进程在操作这块临界区的内存。
如果文件不存在那么便创建这个文件(注意测试和创建是原子操作)。这时如果别的进程如 B 进程需要访问呢这个临界,那么 B 进程的open调用
就会出错,B 也就知道了这是已经有一个进程在操作这块共享内存。然后当 A 操作完了后调用unlink()删除open()创建的文件。那么之后如果别的进
程在想访问这个共享内存,那么就被允许它开始独占访问了。

这里 我们写一个测试的例子:
我们让 A进程和 B进程 同时运行。a进程先测试 temp文件 在不在,不在则调用O_excl创建临时文件同时每一秒输出 A is running持续3秒,之后删除
临时文件然后休息三秒.此时B进程每隔一秒不断尝试独占式访问 ,当发现到 A 进程 正在独占式访问,那么 B 就等待一秒后继续尝试.直到A 退出
临界区(删除临时文件)。然后B开始独占式访问,A休息完后则开始尝试再次取得独占式访问·····如此循环。
(注意这里并没有什么共享内存,我们只是用输出模拟独占式访问)。

A程序如下:
 8         while(1){
  9                 if(open("temp",O_RDWR | O_EXCL | O_CREAT,0666)==-1){
 10                         sleep(1);
 11                 }else{
 12                         for(i=0;i<3;i++){
 13                                 printf("A is running\n");
 14                                 sleep(1);
 15                         }
 16                         if(unlink("temp")==-1){
 17                                 perror("unlink error");
 18                         }
 19                         sleep(3);
 20                 }
 21 
B 进程代码和A进程一样 只是输出改为 B is running.

输出如下(截取部分输出)
B is running
B is running
B is running
A is running
A is running
A is running
B is running
B is running
B is running
A is running
A is running
A is running
B is running
B is running
B is running
A is running
```````
从输出我们可以看出 无论是 A进程 或 B 进程只要开始获得独占式访问。那么A或B就会连续输出3次而不会被中途夺取独占访问权

O_NONBLOCK:如果pathname指的是一个FIFO,一个块特殊文件或一个字符特殊文件,则次选项为文件的本次打开和后续的i/o操作设置
                    非阻塞模式。
关于O_NONBLOCK 请参考(博文里面的 FIFO的O_NONBLOCK参数详解http://blog.chinaunix.net/uid-28852942-id-3656727.html)。

O_NOCTTY:   如果pathname指的是终端设备,则不将该设备分配作为此进程的控制终端。

O_DSYNC:该标志是每次write等待物理I/O操作完成,但是如果写操作并不影响读取刚写入的数据,则不等待文件属性被更新。
        
设置改标志时,仅当文件属性需要更新以反映文件数据变化(例如更新文件大小以反映文件中包含了更多的数据)时,O_DSYNC标志才影响文件属性
比如一个文件有100个数据,我改写了里面的10个数据。那么write调用时只等待文件数据更新后返回,而不等待文件属性更新。(即仅等待数据更新
而不等待文件属性更新)

O_SYNC:该标志使每次write都等到物理I/O操作完成,包括由write操作引起的文件属性更新所需的I/O。
对比与 O_DSYNC 标志  即 无论如何 write都等到 更新文件内容和文件属性I/O完成才返回。(即等待数据和文件属性都更新完)

O_RSYNC: 使每一个以文件描述符作为参数的read操作等待,直至任何对文件同一部分进行的未决写都操作都完成
简单的说 当我们对一个文件的部分read()时,如果之前有这个部分有写入数据,但是并未实际更新磁盘中的文件,则等到实际更新完后才读(即
同步读写)


备注:用Open打开文件时,如果传递给open函数的路径名指定了一个符号链接,那么open跟随此链接到达指定的文件。若此符号链接的文件并不存在,则open函数出错返回。

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