unix之文件IO

原创 2011年01月14日 16:39:00

unix中涉及文件IO的系统调用有:open、write、read、lseek、close。

先说说文件描述符的相关性质:

对于内核来说,所有打开的文件都通过文件描述符引用。文件描述符是一个非负整数。

按照惯例,0(STDIN_FILENO): 标准输入

          1(STDOUT_FILENO):标准输出

          2(STDERR_FILENO):标准错误

这些常量都是在<unistd.h>中定义的

 

1、open :打开或创建一个文件

函数原型:

#include <fcntl.h>

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

返回值 :如果成功返回文件描述符,若出错返回-1

参数:pathname是要打开或创建的文件名称。

      oflag对应的文件状态标志都是定义在<fcntl.h>中的。具体的文件状态标志位自己查阅相关资料

      mode对应的是相关的文件权限模式,后面再讲。

 

注意:open返回的文件描述符一定是最小的未用描述符数值

 

2、creat : 创建一个新的文件

函数原型:

#include <fcntl.h>

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

返回值:如果成功返回为只写打开的文件描述符,若出错则返回-1

      相当于:open(const char* pathname , O_WRONLY | O_CREAT | O_TRUNC , mode);

      所以一般就直接使用open,而不再使用creat。

 

3、close : 关闭一个打开的文件

函数原型:

#include <unistd.h>

int close(int filedes);

 

 

1、read:从打开的文件中读取数据

函数原型:

#include <unistd.h>

ssize_t read( int filedes , void* buf , size_t nbytes );

参数:filedes 文件描述符

  buf 存储读取到的字节内容的缓冲区

      nbytes 准备读取的字节数

返回值:如果调用成功返回读取的字节数 ; 如果已到文件的结尾处则返回; 发生错误   返回-1

其实read在读取文件时,一般都是通过循环,不断读入缓冲区的,所以如果上一次读取操作已经读到了文件的结尾处,那么这一次读取的时候,就会返回0,表明上一次读取已经到了文件的末尾。

这里void* 通用的指针类型,ssize_t 有符号的整数类型 size_t 非负的整数类型。

 

2、write:向打开的文件写数据

函数原型:

#include <unistd.h>

ssize_t write( int filedes , const void* buf , size_t nbytes );

参数:filedes 文件描述符

      buf 准备写入内容的缓冲区

      nbytes 准备写入的字节数

返回值:如果调用成功返回的是写入的字节数 ; 如果发生错误发生 -1 

 

在牵涉到IO读取、写入的时候,如果为了提高IO的效率,那么readwrite操作的buf大小最好设置为unix文件系统中块长的大小,这时候进行IO操作的CPU时间一般是最小的。(这是因为大多数文件系统为了改善其性能都采用某种预读(read ahead)技术,当检测到正在进行顺序读取时,系统就试图读入比应用程序所要求的更多的数据,并假设应用程序很快就会读这些数据)。例如:linux ext2文件系统的块长为4096个字节,块长由st_blksize决定。

 

下面是一个具体的例子:

 

3、fcntl : 可以改变已打开文件的属性

函数原型:

#include <fcntl.h>

int fcntl(int filedes , int cmd , ... /* int arg */) ;

返回值 : 如果成功则依赖于cmd,若错误则返回-1

第三个参数总是一个整数,与上面所示函数原型中的注释部分相对应。但是在作为记录锁用时,第三个参数则是指向一个结构的指针。
   fcntl函数有5种功能:
     1.复制一个现有的描述符(cmd=F_DUPFD.
     2.获得/设置文件描述符标记(cmd=F_GETFDF_SETFD).
     3.获得/设置文件状态标记(cmd=F_GETFLF_SETFL).
     4.获得/设置异步I/O所有权(cmd=F_GETOWNF_SETOWN).
     5.获得/设置记录锁(cmd=F_GETLK,F_SETLKF_SETLKW).
记录锁相关的部分后面再讲解。。。。

fcntl返回的值与命令相关。如果出错,所有命令返回-1,如果成功则返回某个其他值。下面的四个命令有特定的返回值:F_DUPFD(返回新的文件描述符)、F_GETFDF_GETFL(返回相应的标志)、F_GETOWN(返回一个正的进程ID或负的进程组ID

 

下面是一个例子:

 

 

下面还有一个例子:

 

 

注意文件描述符标志和文件状态标志的区别

文件描述符标志指的是fd相关的属性,例如:FD_CLOEXEC等等。

而文件状态标志指的是文件本身的状态,例如:O_RDONLY、O_WRONLY、O_RDWR(三者互斥,只能在创建文件的时候指定其中一种状态标志,不能通过fcntl函数进行改变)其他可以改变的标志有:

 

O_APPEND           每次写时追加

O_NONBLOCK      非阻塞模式

O_SYNC               等待写同步(数据、文件属性)

O_DSYNC             等待写同步(数据)

O_RSYNC             同步读、写

返回值:如果成功返回 0 ,如果失败返回 -1

 

注意:当一个进程终止时,它会自动关闭所有打开的文件。很多程序利用这一点而不显式地调用close()关闭文件。

 

4、lseek :显式地为一个文件设置偏移量

函数原型:

#include <unistd.h>

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

返回值:若成功则返回新的文件的偏移量,若错误则返回-1.

参数:  offset 它的类型是off_t,是带符号的类型,表示偏移量,在一般情况下可正可负。

        whence 它的取值为SEEK_SET(文件开头位置)、SEEK_CUR(当前文件偏移量位置)、SEEK_END(文件的结尾处)

 

注意:1、如果文件描述符引用的是一个管道、FIFO或网络套接字,则lseek返回-1,并将errno设置为ESPIPE。

      2、在默认情况下,除非设置open参数为O_APPEND,文件的偏移量位置总是设置为文件的开始位置。

 

主要总结一下unix中的readwrite函数的使用和相关特性。

这里的文件IO操作:read、write被称为不带缓冲的IO,因为这些操作都在内核执行。

下面一个具体的例子:

4、lseek :显式地为一个文件设置偏移量

函数原型:

漫谈 Unix 中的设备文件

[ 设备文件 ]UNIX具有一种统一的、优美的访问硬件的方法。 在UNIX中,每一个硬件设备都被看作是一个文件。为了说明这个问题,我们来做如下的演示,查看 /dev/hda 这个设备文件:less -...
  • xport
  • xport
  • 2006年04月17日 22:25
  • 2364

UNIX里面关于标准IO的几种缓冲机制

编写背后:国嵌的那段时间,老范曾让我们帮回答下论坛某个会员的问题,代码问题:出不来结果,没任何打印信息; 代码如下():   #i nclude main() {  printf(" if...
  • yx_l128125
  • yx_l128125
  • 2012年03月20日 22:24
  • 1335

【UNIX】什么是IO以及文件IO

I/O输入/输出(Input/Output),分为IO设备和IO接口两个部分
  • CJ_Kano
  • CJ_Kano
  • 2014年11月22日 20:26
  • 382

文件io(一)--unix环境高级编程读书笔记

unix环境高级编程笔记,文件io即不带缓存的io。
  • xiaocainiaoshangxiao
  • xiaocainiaoshangxiao
  • 2013年12月15日 21:07
  • 1992

Unix下五种IO模型简介

阻塞式IO 阻塞式IO模型是最一般的IO模型
  • samuelcoulee
  • samuelcoulee
  • 2014年06月23日 17:32
  • 497

Unix网络编程:阻塞、非阻塞、同步io、异步io的区别

在《Unix 网络编程》一书中讲到:在进行读操作的时候,一般要经历两个步骤,分别是内核准备数据(waiting for the data to be ready)和将数据从拷贝到数据区(copying...
  • Rainloving
  • Rainloving
  • 2015年05月06日 17:08
  • 1293

带缓冲IO与不带缓冲的IO

首先要明白不带缓冲的概念:所谓不带缓冲,并不是指内核不提供缓冲,而是只单纯的系统调用,不是函数库的调用。系统内核对磁盘的读写都会提供一个块缓冲(在有些地方也被称为内核高速缓存),当用write函数对其...
  • u011402017
  • u011402017
  • 2016年12月19日 19:47
  • 245

Linux/UNIX之标准IO库

标准IO库 当打开一个流时,标准I/O函数fopen返回一个指向FILE对象的指针。该对象通常是一个结构,它包含了标准I/O库为管理该流所需的所有信息,包括:用于实际I/O的文件描述符、指向用于该缓...
  • walkerkalr
  • walkerkalr
  • 2014年04月22日 11:55
  • 870

UNIX下的5种IO模型

套接字的IO操作,如recvfrom,分为两个阶段: (1)等待内核中的接收缓冲区中有数据可读。 (2)将接收缓冲区中的数据复制进应用缓冲区。 调用IO操作的进程阻塞不仅指接收缓冲区没有数据时阻塞,数...
  • u014585564
  • u014585564
  • 2016年12月13日 16:29
  • 197

Unix环境高级编程学习笔记(九) 高级IO

fcntl 记录锁 很多时候,当我们有多个进程要访问同一个文件的时候,为了防止多进程访问导致的不一致,我们就要考虑进程间的同步问题了。fcntl是一个非常强大的函数,在这里我们可以使用它来给文件...
  • justaipanda
  • justaipanda
  • 2012年08月28日 17:30
  • 5986
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:unix之文件IO
举报原因:
原因补充:

(最多只允许输入30个字)