APUE笔记-文件IO

文件IO

打开文件

#include<fcntl.h>

open

openat:fd是打开的目录的文件描述符,所以可以写相对路径

掌握:O_RDONLY、O_WRONLY、O_RDWR、O_APPEND、O_CREAT、

O_EXCL:和O_CREAT一起用,测试文件是否存在,存在则出错,否则创建,使得测试和创建成为原子操作。

实验:

第一次执行,创建了hello文件,第二次执行打印:no:File exists

1 #include <stdio.h>                                                                                                                         
  2 #include"apue.h"
  3 
  4 int main()
  5 {
  6     int fd = open("hello",O_CREAT | O_EXCL,0777);
  7     if(fd>0)
  8     {
  9         printf("yes");
 10     }
 11     else
 12     {
 13         perror("no");
 14     }
 15 }

O_NONBLOCK:非阻塞方式,用于FIFO,快特殊文件等。

O_TRUNC:文件存在,并且以写的方式打开,则文件截断为0。

文件名最大长度

#include<limits.h>  NAME_MAX

实验:

打印出:NAME_MAX=255

 #include <stdio.h>                                                                                                                         
  2 #include<limits.h>
  3 
  4 int main()
  5 {
  6     printf("NAME_MAX=%d",NAME_MAX);
  7 }

创建文件

#include<fcntl.h>

creat

相当于:open(path,O_WRONLY | O_CREAT | O_TRUNC,mode)

关闭文件

close

lseek(int fd,off_t offset,int whence);

wence:SEEK_SET(0)文件开始位置计算偏移  SEEK_CUR(1)当前位置  SEEK_END(2)文件末尾

FIFO、管道、网络套接字不可以设置偏移量,调用此函数返回-1,error设为ESPIPE。

实验:测试标准输入能否lseek

打印出:cannot seek: Illegal seek

执行:./a.out < /etc/passwd  打印seek_ok

  1 #include <stdio.h>                                                                                                                         
  2 #include "apue.h"
  3 
  4 int main()
  5 {
  6     if(lseek(STDIN_FILENO,0,SEEK_SET)==-1)
  7     {
  8         perror("cannot seek");
  9     }
 10     else
 11     {
 12         printf("seek ok");
 13     }
 14 }

实验:创建空洞文件

lseek之后必须写入才能创建空洞,空洞不分配磁盘块。

结果:ls -l之后16394字节,因为后面又写入10个字节。

od -c a.out:结果如下

0000000   a   b   c   d   e   f   g   h   i   j  \0  \0  \0  \0  \0  \0
0000020  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0  \0
*
0040000   A   B   C   D   E   F   G   H   I   J
0040012

 

  1 #include <stdio.h>                                                                                                                         
  2 #include"apue.h"
  3 
  4 char buf1[]="abcdefghij";
  5 char buf2[]="ABCDEFGHIJ";
  6 
  7 int main()
  8 {
  9     int fd;
 10     if((fd=creat("file.hole",0777))<0)
 11     {
 12         perror("creat error");
 13     }
 14     if(write(fd,buf1,10)==-1)
 15     {
 16         perror("write error");
 17     }
 18     if(lseek(fd,16384,SEEK_SET)==-1)
 19     {
 20         perror("lseek error");
 21     }
 22     if(write(fd,buf2,10)==-1)
 23     {
 24         perror("write2 error");
 25     }
 26     exit(0);
 27 
 28 }

#include<unistd.h>

read:到达文件末尾,返回0

write

实验:文件复制

 1 #include <stdio.h>                                                                                                                                
  2 #include"apue.h"
  3 #define BUFFSIZE 4096
  4 int main(int argc,char**argv)
  5 {
  6 
  7     int fd_src,fd_dec;
  8     char buf[BUFFSIZE]={0};
  9     int n;
 10     if(argc!=3)
 11     {
 12         printf("error\n");
 13     }
 14     fd_src = open(argv[1],O_RDONLY);
 15     if(fd_src<0)
 16     {
 17         perror("fd_src");
 18     }
 19     fd_dec=open(argv[2],O_CREAT | O_WRONLY,0777);
 20     if(fd_dec<0)
 21     {
 22         perror("fd_dec");
 23     }
 24 
 25     while((n=read(fd_src,buf,BUFFSIZE))>0)
 26     {
 27         if(write(fd_dec,buf,n)<0)
 28         {
 29             perror("write");
 30         }
 31     }
 32     exit(0);
 33 
 34 }

文件共享

 Linux没有V节点,采用了与文件系统相关的i节点和与文件系统无关的i节点。

两个进程打开一个文件,拥有各自的文件表项,每个进程有自己的文件表项,维护自己的文件偏移量。V节点是共享的。

原子操作

1、追加写的步骤:先定位到尾端,然后写。会出问题:两个进程打开同一个文件,A定位到1500,此时进程切换到B,B定位到1500,写了100字节,偏移量为1600,再切换到A进程,A从1500开始写,就把B的数据覆盖掉了。(问题在于采用了分开的函数调用)O_APPEND标志打开文件,实现了原子操作,不需要先lseek再写。

2、O_EXCL | O_CREAT标志,检查文件不存在则创建,也是原子操作。假设分为两个函数,如果检测不存在,此时被另一个进程抢占,并创建文件file,再切换回去,原来的进程创建file,就会擦掉另一进程写到file的数据。

dup和dup2

int dup(int fd)返回的文件描述符和fd指向同一个文件。

int dup2(int fd,inty fd2):关闭fd2指向文件,返回fd2,fd2和fd指向同一个文件,这是原子操作。

延迟写:

写文件时,数据先到缓冲区,排入队列,晚些时候再写。内核要用缓冲区存放其他数据,就把延迟写的内容写到磁盘。

sync没有参数,update守护进程周期调用(一般是30s),定时冲洗缓冲区。

int fsync(int fd)只对fd指定的文件有用。

fdatasync(int fd)只影响文件数据,fsync会同步更新文件属性。

改变打开文件属性

fcntl:命令太多,先掌握三个,复制文件描述符、获取文件状态标志、设置文件状态标志。

O_ACCMODE值为3可以获取打开标志的低三位,代表只读,只写,读写。

实验:open创建文件,测试文件的状态

结果:

read only
write: Bad file descriptor(没有写权限导致的)

换成第10行的,就可以写了。

下面这几行不能修改使得文件可写,F_SETFL允许更改的状态标志有O_APPEND, O_NONBLOCK, O_NOATIME, O_ASYNC和O_DIRECT。系统将忽略对其他标志的修改操作。

val |= O_RDWR;
        if(fcntl(fd,F_SETFL,O_RDWR)<0)
        {
             perror("F_SETFL");
       }
 

1 #include <stdio.h>
  2 #include"apue.h"
  3 
  4 
  5 int main()
  6 {
  7     int fd;
  8     int val;
  9     fd = open("hello",O_CREAT | O_EXCL ,0777);
 10     //fd = open("hello",O_CREAT | O_EXCL | O_RDWR ,0777);                                                                                                  
 11     if(fd<0)
 12     {
 13         perror("open");
 14     }
 15     else
 16     {
 17         val = fcntl(fd,F_GETFL,0);
 18         if(val<0)
 19         {
 20             perror("fcntl");
 21         }
 22         else
 23         {
 24             switch(val&O_ACCMODE)
 25             {
 26             case O_RDONLY:
 27                 printf("read only\n");
 28                 break;
 29             case O_WRONLY:
 30                 printf("write only\n");
 31                 break;
 32             case O_RDWR:
 33                 printf("write read\n");
 34                 break;
 35             default:
 36                 printf("unknow node");
 37                 break;
 38             }
 39         }

可以设置O_SYNC同步写标志,每次写要等待,知道写入到磁盘再返回。不允许用fcntl设置。(APUE  P69)

ioctl函数:先不管。

/dev/fd  目录下看到了0、1、2、255    打开相应文件,相当于复制文件描述符。这些实际是符号链接。(APUE  P71)

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值