文件概述

Linux中,一切皆文件。文件为操作系统服务和设备提供了一个简单而一致的接口。这意味着程序完全可以像使用文件那样使用磁盘文件、串行口、打印机和其他设备。

也就是说,大多数情况下,你只需要使用5个函数: open、close、read、write和ioctl。 例外的情况: 目录的读写,网络连接等特殊文件

目录

文件通常由两部分组成: 内容 + 属性,即管理信息,包括文件的创建修改日期和访问权限等。属性均保存在 inode 节点中。inode - "索引节点",储存文件的元信息,比如

文件的创建者、文件的创建日期、文件的长度和文件在磁盘上存放的位置等等。每个inode都有一个号码,操作系统用inode号码来识别不同的文件。ls -i  查看inode 号。

目录是用于保存其他文件的节点号和名字的文件,每个数据项为指向文件节点的链接。如下图:

当文件链接数变为零,意味文件删除,磁盘空间变成可用空间。

文件和设备

三个重要的设备文件:

/dev/console - 系统控制台。

/dev/tty - 访问不同的物理设备。

/dev/null - 空设备,向所有写这个设备的输出都将被丢弃。

设备驱动程序:

操作系统的核心部分,即内核,是由一组设备驱动程序组成。他们是一组对系统硬件进行控制的底层接口,为了向用户提供一个一致的接口,其封装了所有与硬件相关的特性。

硬件特有功能可通过ioctl(用于I/O控制)系统调用来提供。

/dev 目录下的设备文件都可以被打开、读、写和关闭。

1)open : 打开文件或设备。

2)read : 从打开的文件或设备里读数据。

3)write: 向文件或设备写数据。

4)close: 关闭文件或设备。

5) ioctl:  把控制信息传递给设备驱动程序,每个驱动都由自己的一组 ioctl 命令。

库函数

针对输入输出操作直接使用底层系统调用效率非常低,原因由如下两点。

1)使用系统调用会影响系统性能。

2)硬件会对底层系统调用一次所读写的数据块大小做限制。磁盘:至少一个扇区512

字节,磁带,一次 10K

库函数给设备和磁盘文件提供了更高层的接口,即标准函数库。使用它你可以高效读写任意长度的数据块,库函数则在数据满足条件后再安排系统调用。这样极大降低了开销。

注:库函数的文档一般放在手册的第三页,每个库函数有其对应的头文件。

底层文件访问

运行中的程序称为进程,每个进程都有与之关联的文件描述符。

文件描述符 - 一些小值整数,通过他们访问打开的文件或设备。开始运行会有三个文件描述符:

1)0:   标准输入   STDIN_FILENO

2)1:   标准输出   STDOUT_FILENO

3)2:   标准错误   STDERR_FILENO

文件描述符的变化范围是:0~OPEN_MAX-1 (可通过ulmit -a 查看)

write系统调用

作用:把缓冲区buf 的前count 个字节写入与文件描述符 fd 相关联的文件中。

#include <unistd.h>
size_t write(int fd,const void *buf, size_t count);

描述符出错,文件达到进程限制最大值或设备驱动程序对数据块 长度比较敏感,该返回值可能会小于count,这并不是一个错误。 0 表示未写入数据; -1 表示出错,错误代号在全局变量 errno里。

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h> int main()
{
const char * output = "Hello World\n";
const char * errstr = "A Write error has occurred on file descriptior !\n";
if(write(,output,strlen(output))!=strlen(output));
write(,errstr,strlen(errstr));
exit();
}

read系统调用

作用:作用:从与文件描述符 fd 相关联的文件中读取前count 个字节到缓冲区buf 中。

#include <unistd.h>
size_t write(int fd,const void *buf, size_t count);

它返回实际读入的字节数,这可能会小于请求的字节数。 0 表示未读入任何数据,已到达了文件尾部。 -1 表示出错,错误代号在全局变量 errno里。

#include <unistd.h>
#include <stdlib.h> int main()
{
char buffer[];
int nread = read(,buffer,);
if(nread == -)
write(,"A read error has occurred\n",);
if(write(,buffer,nread)!= nread)
write(,"A write error has occurred\n",); }

open系统调用

作用:创建一个新的文件描述符(文件或设备)。

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h> int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

open 建立一条到文件或设备的访问路径。成功后可获得供 read、write和其他系统调用使用的唯一的文件描述符。此文件描述符进程唯一;如果两个程序打开同一个文件,那么,他们分别得到不同的文件描述符,并可以单独对文件进行独立的操作。我们可以通过文件锁(O_EXCL或FCNTL)功能来解决这个问题。

参数说明:

pathname - 指示准备打开的文件或设备的名字;

flags    - 用于指定打开文件所采取的动作;

mode    - 用于指定创建文件的权限,O_CREATE 才使用。

flags 参数通过必需文件访问模式 与 其他可选模式相结合的方式来指定。 首先必须指定如下文件访问模式之一:

模     式

说    明

O_RDONLY

以只读方式打开

O_WRONLY

以只写方式打开

O_RDWR

以读写方式打开

可选模式组合:

1) O_APPEND: 把写入数据最佳在文件的末尾。

2) O_TRUNC:  打开文件时把文件长度设置为零,丢弃已有的内容。

3) O_CREAT:   如果需要,就按参数mode 中给出的访问模式创建文件。

4) O_EXCL:   与O_CREAT一起使用,确保创建文件的 原子操作。如果文件存在,创建 将失败

访问权限的初始:

单个权限设置     : S_I  R或W或X    USR或GRP或OTH

读写执行全权限 : S_I RWX             U或G或O

如: S_IRUSR    读权限  文件属性

   S_IRWXO   读写执行  其他用户

最终权限生成还和进程设置的umask权限掩码有关,执行umask命令或者函数 可以改变权限。

新文件描述符总使用未用文件描述符的最小值。如果一个文件符被关闭再次调用open ,其马上会被重用。

!Posix 规定了一个 creat 调用:  等同于  O_CREAT|O_WRONLY|O_TRUNC

close系统调用

作用:终止文件描述符fd 和对应文件(文件或设备)的关联。文件描述符被释放并能够重新使用。close 调用成功返回0,出错返回 -1。

#include <unistd.h>
int close(int fd);

返回值: 检查 close 调用的返回值很重要。可以检测某些写操作错误!

ioctl系统调用

ioctl提供了一个用于控制设备及其描述行为和配置底层的服务的接口。终端文件描述符、套接字都可以定义他们的ioctl,具体需要参考特定设备的手册。

#include <sys/ioctl.h>

int ioctl(int d, int request, ...);

dup和dup2的系统调用

作用:提供了一种复制文件描述符的方法,是我们通过两个或者更多不同的描述符来访问同一个文件,主要用于多个进程间进行管道通信。

#include <unistd.h>

       int dup(int oldfd);
int dup2(int oldfd, int newfd);

lseek系统调用

作用:

作用:lseek 对文件描述符 fd 的读写指针进行设置。也就是说,设置文件的下一个读写位置。可根据绝对位置和相对位置(当前位置或文件尾部)进行设置。

#include <sys/types.h>
#include <unistd.h> off_t lseek(int fd, off_t offset, int whence);

offset 参数用来指定位置,而whence 参数定义该偏移值的用法。Whence 可取值如下:

1)SEEK_SET:     offset 是一个绝对位置。

2)SEEK_CUR:    offset 是相对于当前位置的一个相对位置。

3)SEEK_END:    offset 是相对于文件尾的一个相对位置。

lseek 返回从文件头到文件指针被设置处的字节偏移值,失败时返回-1.

fstat、stat和lstat系统调用

作用:获取文件的状态信息,该信息将会写入一个buf中,buf的地址会以参数的形式传递给fstat

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h> int stat(const char *path, struct stat *buf);
int fstat(int fd, struct stat *buf);
int lstat(const char *path, struct stat *buf);

stat 和 lstat 均通过文件名查询状态信息,当文件名是符号链接时,lstat返回的时符号链接本身的信息,而stat 返回的时改链接指向的文件的信息。

struct stat {
dev_t st_dev; /* ID of device containing file */
ino_t st_ino; /* inode number */
mode_t st_mode; /* protection */
nlink_t st_nlink; /* number of hard links */
uid_t st_uid; /* user ID of owner */
gid_t st_gid; /* group ID of owner */
dev_t st_rdev; /* device ID (if special file) */
off_t st_size; /* total size, in bytes */
blksize_t st_blksize; /* blocksize for filesystem I/O */
blkcnt_t st_blocks; /* number of 512B blocks allocated */
time_t st_atime; /* time of last access */
time_t st_mtime; /* time of last modification */
time_t st_ctime; /* time of last status change */
};

这里要特别提到的是,以上 st_mode 标志有一系列相关的宏,定义见 sys/stat.h 中

,可用来测试文件类型,如:

错误处理

许多系统调用和函数都会因为各种各样的原因失败。他们失败时设置外部变量errno 来知名失败原因。许多不同函数库都把这个变量用做报告错误的标准方法。

注意: 程序必须在函数报告出错 之后立刻检查errno 变量,因为它可能马上就被下一个函数调用所覆盖,即使下一个函数没有出错,也可能会覆盖这个变量。

常用错误代码的取值和含义如下:

l   EPERM:     操作不允许

l   ENOENT:   文件或目录不存在。

l   EINTR:     系统调用被中断。

l   EAGAIN:    重试,下次有可能成功!

l   EBADF:     文件描述符失效或本身无效

l   EIO:        I/O错误。

l   EBUSY:     设备或资源忙。

l   EEXIST:     文件存在。

l   EINVL:      无效参数。

l   EMFILE:     打开的文件过多。

l   ENODEV:    设备不存在。

l   EISDIR:      是一个目录。

l  ENOTDIR:     不是一个目录。

两个有效函数可报告出现的错误: strerror  和 perror。

strerror 函数

  作用:把错误代号映射成一个字符串,该字符串对发生的错误类型进行说明。

#include <string.h>
char *strerror(int errnum);
int strerror_r(int errnum, char *buf, size_t buflen);

perror函数

作用:perror 函数也把errno 变量中报告的当前错误映射成一个字符串,并把它输出到标准错误输出流。

perror(“test”);

结果:

Test: Too many open files

Linux文件IO操作函数概述的更多相关文章

  1. Linux文件IO操作

    来源:微信公众号「编程学习基地」 目录 文件操作 Linux文件类型 Linux文件权限 修改文件权限 Linux error 获取系统调用时的错误描述 打印错误信息 系统IO函数 open/clos ...

  2. linux文件IO操作篇 (一) 非缓冲文件

    文件IO操作分为 2 种 非缓冲文件IO 和 缓冲文件IO 它们的接口区别是 非缓冲 open() close() read() write() 缓冲 fopen() fclose() fread() ...

  3. C标准库函数--文件IO操作函数。

    C标准库文件读写函数总结:都是对文件流进行输入输出的函数分为对文件的有格式读写以及无格式读写 一.文件的无格式读写根据每次读写字符的数量,分为三类:1.按字符读写文件 按字符读有三个函数:以下三个函数 ...

  4. linux文件IO操作篇 (二) 缓冲文件

    2. 缓冲文件操作 //规模较大 实时性低的文件 //当数据长度快要超过缓冲区的范围时,或者时间周期达到时,数据才被送往指定位置 //需要使用FILE * 作为文件标识符 //stdin 标准输入 / ...

  5. 转:Linux 文件IO理解

    源地址http://blog.csdn.net/lonelyrains/article/details/6604851 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件 ...

  6. Linux学习记录--文件IO操作相关系统编程

    文件IO操作相关系统编程 这里主要说两套IO操作接口,各自是: POSIX标准 read|write接口.函数定义在#include<unistd.h> ISO C标准 fread|fwr ...

  7. 2.Linux文件IO编程

    2.1Linux文件IO概述 2.1.0POSIX规范 POSIX:(Portable Operating System Interface)可移植操作系统接口规范. 由IEEE制定,是为了提高UNI ...

  8. 树莓派学习笔记——使用文件IO操作GPIO SysFs方式

    0 前言     本文描写叙述假设通过文件IO sysfs方式控制树莓派 GPIO端口.通过sysfs方式控制GPIO,先訪问/sys/class/gpio文件夹,向export文件写入GPIO编号, ...

  9. C语言对文件的操作函数用法详解2

    fopen(打开文件) 相关函数 open,fclose 表头文件 #include<stdio.h> 定义函数 FILE * fopen(const char * path,const  ...

随机推荐

  1. fabric-ca安装

    1.Go版本1.7+(具体可参考Linux安装Go语言) 2.GOPATH环境变量正确配置 export GOROOT=/usr/local/go export GOPATH=/opt/gopath ...

  2. 开源G711(PCMA、PCMU)/G726转AAC项目EasyAACEncoder

    EasyDarwin开源社区整理了一份G711(PCMA.PCMU)/G726转AAC的转码库,支持Windows/Linux跨平台使用,将安防标准的G711转成移动互联网常用的AAC格式,希望能给大 ...

  3. asp.net mvc4 之Webapi之应用客户端访问服务器端

    一.说明 客户端项目类型设计为:winform(winform窗体项目类型) 服务器端项目类型设计为:asp.net mvc4  webapi 在这里分为项目运行和调试两种情况讨论: 运行: 这种情况 ...

  4. (t,p,o) t:p>=o there cannot be more consumer instances in a consumer group than partitions

    https://kafka.apache.org/intro.html Kafka as a Messaging System How does Kafka's notion of streams c ...

  5. ckeditor html标签的class 等attribute属性都被屏蔽啦,替换成空的解决方案

    ckeditor 模块中自定义class 在ckeditor模块中,编辑内容时, 在源码中填写<div class="myclass">some content< ...

  6. vim实现代码缩进和可视区域的字符串替换

    今天2014年9月12号,实现了vim下的代码自动缩进和替换可视区域的字符串,之前一直在用vim这个强大的编辑器,它的强大只有用了的人才知道,现在把这两个很强大的功能展示出来,有个这两个功能,即使你写 ...

  7. Linux-Nginx和NFS

    1 虚拟化 查看系统信息 cat /proc/meninfo cat /proc/cpuinfo 其中 flags里面的信息可以查看该cpu是否支持虚拟化 flags上有vmx svm等表示可以虚拟化 ...

  8. 编程模式(schema) —— 表驱动法(table-driven)

    使用表驱动法,而非繁琐冗长的 if/else, switch case(本身也代表一种代码坏味道),也是替身编程质量的重要手段, 表驱动法是一种编程模式(schema)-- 从表里面查找信息而不使用逻 ...

  9. bootstrap 学习笔记(5)---- 图片和响应式工具

    (一)响应式图片: 在 Bootstrap 版本 3 中,通过为图片添加 .img-responsive 类可以让图片支持响应式布局.其实质是为图片设置了 max-width: 100%;. heig ...

  10. BZOJ_2850_巧克力王国_KDTree

    BZOJ_2850_巧克力王国_KDTree Description 巧克力王国里的巧克力都是由牛奶和可可做成的.但是并不是每一块巧克力都受王国人民的欢迎,因为大家都不喜 欢过于甜的巧克力.对于每一块 ...