File I/O

转自http://blog.youkuaiyun.com/cinmyheart/article/details/18924241

File I/O


文件I/O

在Unix系统中,文件I/O大多数的使用五大函数来实现:open,read,write,lseek 和close.

术语unbuffered的意思是每个read或者write函数向内核请求一个系统调用


对于内核而言,每一个打开的文件都有相应的file descriptors(非负整数).


open 函数

#include<fcntl.h>

int open(const char* pathname,int oflag,......,/*  mode_t mode  */);

如果正确返回file descriptor,否则返回 -1

pathname是文件名的路径,oflag是option flag,选项标签这里的选项是宏定义

oflag宏:

O_RDONLY    只可读

O_WRONLY  只可写

O_RDWR        可读写

O_APPEND    对于每个write函数的写入点从当前文件末尾开始

O_CREAT      如果文件不存在,就创建这个文件。

当然这个对于open函数使用的选项需要和函数的第三个参数mode一起,mode用于描述新建文件的权限

O_EXCL      如果使用了O_CREAT宏,并且这个文件已经存在了,于是 产生一个错误

O_TURNC   如果文件存在了并且被每一个write或者read函数成功的打开了,这个选项将“命令“open函数去清空所有文件内容,使之文本长度为0.

O_NOCTTY  如果pathname提及的是terminal设备,不允许设备被作为controling terminal 

O_DSYNC   使得write等待每一个物理I/O完成自己的工作,但是不等待那种不影响读取刚写入的数据的文件

O_RSYNC     在任何write操作对于某一文件的同一部分写入操作完成之前,让被read操作的file descriptor所指的文件保持等待

  1. <span style="font-size:14px;">/*************** 
  2. just a demo 
  3. ***************/  
  4. #include"apue.h"  
  5. #include"fcntl.h"  
  6. #include"stdio.h"  
  7.   
  8. int main()  
  9. {  
  10.     int file_descriptor = 0;  
  11.   
  12.     if(file_descriptor = open("./text.t",O_RDONLY) < 0)  
  13.     {  
  14.         printf("open error\nprocess end\n");  
  15.         return 0;  
  16.     }  
  17.     else  
  18.     {  
  19.         printf("open success\n");  
  20.         close(file_descriptor);//if there is not close function ,it would be OK...  
  21.     }  
  22.     return 0;  
  23. }</span>  


creat 函数

#include<fcntl.h>

int creat(const char* pathname,mode_t mode);

如果函数成功就返回打开的文件的file descriptor,否则返回-1

mode :

 S_IRUSR   用户可读

 S_IWUSR   用户可写

 S_IXUSR   用户可执行

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include<apue.h>  
  2. #include<unistd.h>  
  3. #include<fcntl.h>  
  4.   
  5. #define RWX  (S_IRUSR | S_IWUSR | S_IXUSR)  
  6.   
  7. int main()  
  8. {  
  9.     int file_descriptor = 0;  
  10.       
  11.     if((file_descriptor = creat("./hello.t",RWX)) < 0)  
  12.     {  
  13.         printf("creat fail\nprocess end");  
  14.         return 0;  
  15.     }  
  16.     else  
  17.     {  
  18.         printf("creat successful\n");  
  19.     }  
  20.       
  21.     close(file_descriptor);  
  22.     return 0;  
  23. }  



close函数

#include<unistd.h>

int  close(int filedes)

如果成功返回0,否则返回-1


每个文件都有一个相关的“当前文件偏置”(current file offset),通常是一个非负整数。它测量表示的意义是从文件开头到结束的地方这段区域内,所含字节数。

read函数write函数的读写操作通常从这个offset开始

通常(default情况),offset被初始化为0.


lseek函数

#include"unistd.h"//unistd.h - standard symbolic constants and types

off_t lseek(int files,  off_t offset,   int whence)

如果成功返回file offset,否则返回-1

whence宏:

SEEK_SET 将文件的offset设置为文件开头

SEEK_CUR将文件的offset设置为当前值加上lseek的第二参数offset的值(offset必须为正数)

SEEK_END将文件的offset设置为文件的大小加上lseek的第二个参数offset的值(offset可正可负)

  1. <span style="font-size:14px;">/* 
  2. just a demo for lseek 
  3. */  
  4. #include"apue.h"  
  5. #include"stdio.h"  
  6. #include"unistd.h"  
  7. #include"fcntl.h"  
  8.   
  9. int main()  
  10. {  
  11.     off_t file_off_set = 0;  
  12.     int file_descriptor = 0;  
  13.       
  14.     if((file_descriptor = open("./text.t",O_RDONLY)) < 0)  
  15.     {  
  16.         printf("open error\nProcess end\n");  
  17.         return 0;  
  18.     }  
  19.       
  20.     if((file_off_set = lseek(file_descriptor,file_off_set,SEEK_CUR)) < 0)  
  21.     {  
  22.         printf("lseek error\n");  
  23.         return 0;  
  24.     }  
  25.     else  
  26.     {  
  27.         printf("lseek execute successful\nCurent file off-set is %d\n",file_off_set);  
  28.     }  
  29.     return 0;  
  30. }</span>  







atomic operation微操作

[csharp]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">#inlcude<unistd.h>  
  2. ssize_t pread(int filedes, void * buf,size_t nbytes,off_t offset);</span>  
[csharp]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <span style="font-size:14px;">ssize_t pwrite(int filedes,const void*buf,size_t nbytes,off_t offset);</span>  

调用pread函数就相当于调用lseek函数之后紧接着调用read函数。这两者几乎是等价的,除了下面两点情况

1.调用pread的时候, 没有什么办法可以打断这两者(lseek和read)操作

2.文件指针没有更新

pwrite同理


          简单的说,atomic operation就是指的一种操作。这种操作可能由其他多种操作组成(multiple step)。

这个atomic operation有个特点,就是这个atomic operation包含的操作步骤(step)要么都完成,要么都不

会开始进行。这个atomic operation中不会有其他的操作“夹杂着"发生。

下面是man pwrite 的结果:

pwrite()  writes  up  to  count  bytes from the buffer

starting at buf to the file descriptor  fd  at  offset     

The file offset is not changed.


         值得注意的是这里的offset 是个定值而不是动态获得的,也就是说可能覆盖之前的文本内容(亲测,有这个情况)

如果要动态更新offset达到,每次都在 “新的文本末尾" 写入数据的话,那么则需要lseek和SEEK_END来实现更新offset

动态更新的在文本末尾写入数据用pwrite是没有必要的,lseek+write就可以了

my source code:

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include"unistd.h"  
  2. int dup(int fd);  
  3. int dup2(int fd,int fd2)  
  4. 对于file descriptor的复制  

              These  system calls create a copy of the file descriptor oldfd. dup() uses the lowest-numbered unused descriptor  for the new descriptor.  dup2() makes newfd be the copy of oldfd, closing newfd  first if necessary, but note the following: 
        *  If oldfd is not a valid file descriptor,  then  the call fails, and newfd is not closed.    
        *  If  oldfd is a valid file descriptor, and newfd has the same value as oldfd, then dup2() does  nothing,  and returns newfd.

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include"apue.h"  
  2. #include"unistd.h"  
  3. #include"fcntl.h"  
  4. int main()  
  5. {  
  6.     int file_descriptor = 0;  
  7.     int duped_fd = 0;  
  8.     if((file_descriptor = open("./text.t",O_RDONLY)) < 0)  
  9.     {  
  10.         printf("open error\nprocess end\n");  
  11.         return 0;  
  12.     }  
  13.     else  
  14.     {  
  15.         duped_fd = dup(file_descriptor);  
  16.         printf("The duped file descriptor is %d\n",duped_fd);  
  17.         printf("The file_descritor before dup:%d\n",file_descriptor);  
  18.     }  
  19.     return 0;  
  20. }  

NAME
       fsync,  fdatasync - synchronize a file's in-core state  with storage device

[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include <unistd.h>  
  2.   
  3. int fsync(int fd);  
  4.   
  5. #include<fcntl.h>  
  6. int fcntl(int filedes, int cmd,.../*int arg*/);  

filedes文件标志符
cmd是参数宏,总共有十个,第三章只讨论前面七个,后面三个再第14章讨论
在秒速记录锁(record locking)的时候,第三个参数是一个指向结构体的指针
fcntl被用作五种不同的路径
第一,复制已经存在的文件标志符(descriptor)cmd  = F_DUP
第二,设置或者获得文件标识符cmd = F_GETFD或者 cmd = F_SETFD
第三,设置或者获得状态符(status flag) cmd = F_GETFL或则F_SETFL
status flag: 

     O_RDWR

     O_RDONLY
     O_WRONLY
     O_APPEND
     O_NONBLOCK
     O_SYNC
     O_DSYNC
     O_RSYNC
     O_FSYNC

     O_ASYNC

第四,设置或则获得异步I/O权限(asynchronous I/O ownership)cmd = F_GETOWN or cmd = F_SETOWN
第五,设置或者获得记录锁(record lock)(cmd = F_GETLK, or cmd = F_SETLK)


[objc]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. #include<apue.h>  
  2. #include<fcntl.h>  
  3. #include<stdio.h>  
  4. int main()  
  5. {  
  6.     int file_descriptor = 0;  
  7.     int copy_file_descriptor = 0;  
  8.     int file_flags = 0;  
  9.     int ownership = 0;  
  10.     int temp = 0;  
  11.   
  12.   
  13.     if((file_descriptor = open("./text.t",O_RDWR)) < 0)  
  14.     {  
  15.         printf("open error\nProcess end\n");  
  16.         return 0;  
  17.     }  
  18.   
  19.   
  20.     printf("file_descriptor is %d\n",file_descriptor);  
  21.   
  22.   
  23.     //cmd = F_DUPFD ,dupliacte the file descriptor  
  24.     if((copy_file_descriptor = fcntl(file_descriptor,F_DUPFD,0)) < 0)  
  25.     {  
  26.         printf("fcntl error\nProcess end");  
  27.         return 0;  
  28.     }  
  29.     else  
  30.     {  
  31.         printf("The return value is %d\n",copy_file_descriptor);  
  32.     }  
  33.       
  34.     //cmd = F_GETFD, return file descriptor flass for fiedes as the vale of the fucntion  
  35.     if(temp = fcntl(file_descriptor,F_GETFD) < 0)  
  36.     {  
  37.         printf("fcntl error\nProcess end\n");  
  38.         return 0;  
  39.     }  
  40.     else  
  41.     {  
  42.         printf("file descriptor is %d\n",temp);  
  43.     }  
  44.       
  45.     //cmd = F_GETFL,return file status flags for filedes.  
  46.     if(file_flags = fcntl(file_descriptor,F_GETFL) < 0)  
  47.     {  
  48.         printf("fcntl error\nProcess end\n");  
  49.         return 0;  
  50.     }  
  51.     else  
  52.     {  
  53.         switch(file_flags& O_ACCMODE) //& O_ACCMODE)  
  54.         {  
  55.             case O_RDWR  :  
  56.                 printf("file flags is O_RDWR\n");  
  57.                 break;  
  58.             case O_RDONLY:  
  59.                 printf("file flags is O_RDONLY\n");  
  60.                 break;  
  61.             case O_WRONLY:  
  62.                 printf("file flags is O_WRONLY\n");  
  63.                 break;  
  64.         }  
  65.   
  66.   
  67.         if(file_flags&O_APPEND)  
  68.         {  
  69.             printf("file flags is O_APPEND\n");  
  70.         }     
  71.         if(file_flags&O_NONBLOCK)  
  72.         {  
  73.             printf("file flags is O_NONBLOCK\n");  
  74.         }  
  75.           
  76.         #if defined(O_SYNC)  
  77.         if(file_flags&O_SYNC)  
  78.         {     
  79.             printf("file flags is O_SYNC\n");  
  80.         }  
  81.         #endif  
  82.       
  83.         #if defined(O_DSYNC)  
  84.         if(file_flags&O_DSYNC)  
  85.         {  
  86.             printf("file flags is O_DSYNC\n");  
  87.         }  
  88.         #endif  
  89.           
  90.         #if defined(O_FSYNC)  
  91.         if(file_descriptor&O_FSYNC)   
  92.         {  
  93.             printf("file flags is O_FSYNC\n");  
  94.         }  
  95.         #endif  
  96.           
  97.         #if defined(O_ASYNC)  
  98.         if(file_descriptor& O_ASYNC)  
  99.         {  
  100.             printf("file flags is O_ASYNC\n");  
  101.         }         
  102.         #endif  
  103.       
  104.         #if defined (O_RSYNC)  
  105.         if(file_descriptor&O_RSYNC)  
  106.         {  
  107.             printf("file flags is O_RSYNC\n");  
  108.         }  
  109.         #endif  
  110.     }  
  111.       
  112.     //cmd = F_GETOWN  
  113.     if(ownership = fcntl(file_descriptor,F_GETOWN) < 0)  
  114.     {  
  115.         printf("fcntl error!\nProcess end\n");  
  116.         return 0;  
  117.     }  
  118.     else  
  119.     {  
  120.         printf("file ownership is %d",ownership);  
  121.     }  
  122.   
  123.   
  124.     return 0;  
  125. }  

在 /dev/fd文件夹目录下的文件,如果被打开,相当于复制该文件标志符。












[csharp]  view plain copy print ? 在CODE上查看代码片 派生到我的代码片
  1. <pre code_snippet_id="177568" snippet_file_name="blog_20140205_8_7827139" name="code" class="csharp"><pre code_snippet_id="177568" snippet_file_name="blog_20140205_8_7827139"></pre>  
  2. <pre></pre>  
  3. <pre></pre>  
  4. <pre></pre>  
  5. <pre></pre>  
  6. <pre></pre>  
  7. <pre></pre>  
  8. <pre></pre>  
  9. <pre></pre>  
  10. <pre></pre>  
  11. <pre></pre>  
  12. <pre></pre>  
  13.   
  14. </pre>  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值