一、概述

Unix文件操作常用函数包括openclosecreatlseekdupdup2fcntl等,

其中open、creat、 fcntl函数需要包含头文件<fcntl.h>,

其余几个函数需要包含头文件<unistd.h>。

由于在Linux操作系统 中使用man命令可以非常方便的查找函数原型及示例,这里就不帖出函数原型了,只讲一下使用时需要注意的地方。

二、文件描述符

每一个在程序中打开的文件都有一个相应的文件描述符(file descriptor),Unix操作系统中的文件描述符保存在/dev/fd目录下。

每一个进程对该目录读取到的结果都不想同(视该进程正在使用的文件 数而定)。

如果由open函数直接读取该路径下的文件,将视为在此进程中对该文件描述符所对应的文件进行dup操作,在大多数操作系统中将忽略打开方式, 而部分操作系统要求打开方式为所涉及文件原先打开方式的子集。

三、Flags

当使用O_APPEND方式打开文件时,每次调用write函数会在文件最后面写入新数据,调用write函数后读取当前文件偏移量 (current offset)可以很清楚的看到该值与文件最大偏移量相等。

如果使用了O_RDWR | O_APPEND方式打开文件,程序可以对该文件在任意位置实现读取操作(read),但写入操作(write)会使文件偏移量被重置,如果读取与写入混 合使用,可能会导致读取位置出现偏差。

四、函数细说

4. 1 creat & open  

  creat函数与

open(pathname, O_WRONLY | O_CREAT | O_TRUNC, mode);

  等同,使用creat函数的缺陷在于如果需要在创建的同时读写该文件,需要在创建后将文件关闭,重新以读写方式open该文件,相对而言,下面的调用方式更为简单:

open(pathname, O_RDWR | O_CREAT | O_TRUNC, mode);

  其中,O_TRUNC表示:如果此文件存在,而且为只读或只写成功打开,则将其长度截短为0(即会清空文件内容)

4.2 lseek

  在lseek函数中,偏移量(offset)是一个长整型,可正可负。如果偏移量大于文件最大偏移量,对该位置进行写入操作,将对文件进行扩展,文件中的空洞(从原文件最大偏移量到写入位置)被填充为0,但并不占用磁盘块

  例如:

fd = creat("file.txt", S_IRWXU);
lseek(fd,,SEEK_SET);
write(fd,"abcdefg",);

  程序执行后,使用"ls -ls file.txt"命令可以看出,文件file.txt所占块数为8.

 4.3 read

  使用read函数时,遇到以下情况会使read函数提前返回:

  • 文件读取遇到EOF。
  • 从终端中读取到一行内容。(STDIN_FILENO)
  • 当从网络读时,网络中的缓冲机构可能造成返回值小于所要求读的字节数。
  • 从管道或FIFO中读取到全部内容。
  • 某些面向记录的设备,例如磁带,一次最多返回一个记录。
  • 接收到中断信号。

五、File Sharing

5.1 说明

  在进程中,一个进程所打开的所有文件描述符存放在一个table中,table中的每条记录包括文件描述符falgs(file descriptor flags)和指向文件表的指针(fils pointer)。

  一个文件表包含一个文件的状态标志(file status flags),当前偏移量(offset),一个指向v-node表的指针。一个v-node表包括v-node信息,i-node信息,文件大小等。如 图1所示:

图1. Unix文件表(进程中)

  在多个进程中,可能出现多个文件描述符指向同一个文件,此时如图2所示:

图2. 多个进程中同时打开同一个文件

  当使用dup、dup2函数后,文件描述符将被复制,此时如图3所示:

图3. dup后多个文件描述符指向同一个file table

5.2 控制多进程对文件的访问

  在进行多进程或多线程编程时,由于无法控制CPU对进程和线程的调度,如果不加以控制,可能会在任意两条程序控制语句中间出现中断,导致数据被污染。

  可以使用原语来保证在特定操作中数据不会被污染,使数据同步。

  原语形式的文件读写函数为 pread和pwrite。

  也正因为数据可能被污染的原因,虽然dup2(file1,file2)与close(file2); fcntl(file1, F_DUPFD, file2)等价,但第一个函数不会导致数据被污染,我们应该使用第一个函数。

5.3 文件更新

  在操作系统中,向文件中写入数据往往只是暂时写入至操作系统缓存中,由操作系统控制磁盘中文 件的更新时间。使用sync、fsync、fdatasync函数可以实现磁盘中文件的实时更新。

  使用sync函数时,文件表中的所有文件将被更新。

  fsync函数只更新制定文件。

  fdatasync函数只更新指定文件中的数据内容,而不更新相应的文件属性。

  如果file status flags中O_SYNC标志被设置,程序中每次对该文件的write操作都将导致文件被更新;如果O_DSYNC被设置,程序中每次对该文件的write操作都将导致文件中的数据部分被更新。

 5.4 fcntl

  fcntl函数可以修改已打开文件的属性。

  当使用fcntl函数获取文件状态标记(file status flags)时,由于O_RDONLY、O_WRONLY、O_RDWR标记具有排外型,无法被直接识别,需要由O_ACCMODE掩码转换后才可以被识 别。

  示例代码如下:

#include <fcntl.h>
int
main(int argc, char *argv[])
{
int val;
if (argc != )
    err_quit("usage: a.out <descriptor#>");
if ((val = fcntl(atoi(argv[]), F_GETFL, )) < )
    err_sys("fcntl error for fd %d", atoi(argv[]));
switch (val & O_ACCMODE) {
    case O_RDONLY:
    printf("read only");
    break;
case O_WRONLY:
    printf("write only");
    break;
case O_RDWR:
    printf("read write");
    break;
default:
    err_dump("unknown access mode");
}
if (val & O_APPEND)
    printf(", append");
if (val & O_NONBLOCK)
    printf(", nonblocking");
#if defined(O_SYNC)
if (val & O_SYNC)
    printf(", synchronous writes");
#endif
#if !defined(_POSIX_C_SOURCE) && defined(O_FSYNC)
if (val & O_FSYNC)
printf(", synchronous writes");
#endif
putchar('\n');
exit();
}

Unix文件操作的更多相关文章

  1. unix文件操作函数

    1. fopen函数 #include <stdio.h> FILE *fopen(const char *path, const char *mode) 返回:文件顺利打开后,指向该流的 ...

  2. 编写who命令:文件操作,缓冲区与联机帮助

    最近阅读UULP(Understanding Unix/Linux Programming),按照书中介绍对Unix/Linux系统编程进行学习梳理,总结如下. 1. who命令能做什么 who命令用 ...

  3. Unix无缓冲文件操作函数、文件信息查询

    问题描述:         Unix无缓冲文件操作函数.文件信息查询 问题解决:        struct stat 结构体信息: 具体代码: 具体源文件:

  4. Unix/Linux常用文件操作

    Unix/Linux常用文件操作 秘籍:man命令是Unix/Linux中最常用的命令,因为命令行命令过多,我相信每个人都会经常忘记某些命令的用法,man命令就可以显示一个命令的所有选项,参数和说明, ...

  5. Unix/Linux环境C编程入门教程(41) C语言库函数的文件操作详解

     上一篇博客我们讲解了如何使用Linux提供的文件操作函数,本文主要讲解使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...

  6. Unix/Linux环境C编程新手教程(41) C语言库函数的文件操作具体解释

     上一篇博客我们解说了怎样使用Linux提供的文件操作函数,本文主要解说使用C语言提供的文件操作的库函数. 1.函数介绍 fopen(打开文件) 相关函数 open,fclose 表头文件 #in ...

  7. C语言的fopen函数(文件操作/读写)

    头文件:#include <stdio.h> fopen()是一个常用的函数,用来以指定的方式打开文件,其原型为:    FILE * fopen(const char * path, c ...

  8. python 文件操作(转)

    python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目 ...

  9. python文件操作

    总是记不住API.昨晚写的时候用到了这些,但是没记住,于是就索性整理一下吧: python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Pyth ...

随机推荐

  1. 生成订单唯一id

    $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J'); $orderSn = $yCode[intval(date('Y') ...

  2. 简单的html5 File base64 图片上传

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  3. PHP之验证码识别

    首先推荐几篇有关验证码识别的文章,觉得不错 php实现验证码的识别(初级篇) 关于bp神经网格识别验证码 一.思路 碰见一个验证码,如果我们想要识别它,我们需要的是做什么呢? 我们先观察几个验证码.. ...

  4. Java中权限修饰符public、private、protected和default的区别

    1.public 可以修饰类.成员变量和成员函数,没有任何限制,同一个包中,或者不同包中的类都可以自由访问 2.private 可以修饰成员变量和成员函数,只能在本类中使用 3.default (不写 ...

  5. ha666_go运行环境配置

    项目地址:http://git.oschina.net/ha666/ha666_go 服务器配置: CPU: 1核 内存: 1024 MB 操作系统: CentOS 7.0 64位 内网IP: 10. ...

  6. index rang scan

    根:分支的范围,范围块的地址 ----- begin tree dump branch: 0x1000c93 16780435 (0: nrow: 5, level: 1)    leaf: 0x10 ...

  7. POJ- 2104 hdu 2665 (区间第k小 可持久化线段树)

    可持久化线段树 也叫函数式线段树也叫主席树,其主要思想是充分利用历史信息,共用空间 http://blog.sina.com.cn/s/blog_4a0c4e5d0101c8fr.html 这个博客总 ...

  8. Qt入门(10)——调试技术

    命令行参数当你运行Qt程序时,你可以指定几个命令行参数来帮助你调试.-nograb 应用程序不再捕获鼠标或者键盘.当程序在Linux下运行在gdb调试器中时这个选项是默认的.-dograb 忽略任何隐 ...

  9. Visual Studio Code尝试体验

    背景了解 偶然间看到一篇大赞Visual Studio Code的文章,就搜索了一下,发现网上基本一致的好评.虽然微软在2015年4月29号 Build 2015 大会上才发布,但免费,轻量,跨平台版 ...

  10. 数据结构:(平衡树,链表)BZOJ 1588[HNOI2002]营业额统计

    1588: [HNOI2002]营业额统计 Time Limit: 5 Sec  Memory Limit: 162 MBSubmit: 12173  Solved: 4354[Submit][Sta ...