linux 文件IO

1、文件描述符

(1)文件描述符的本质是一个数字,这个数字本质上是进程表中文件描述符表的一个表项,进程通过文件描述符作为index去索引查表得到文件表指针,再间接访问得到这个文件对应的文件表。
(2)文件描述符这个数字是open系统调用内部由操作系统自动分配的,操作系统分配这个fd时也不是随意分配,也是遵照一定的规律的,我们现在就要研究这个规律。
(3)操作系统规定,fd从0开始依次增加。fd也是有最大限制的,在linux的早期版本中(0.11)fd最大是20,所以当时一个进程最多允许打开20个文件。linux中文件描述符表是个数组(不是链表),所以这个文件描述符表其实就是一个数组,fd是index,文件表指针是value
(4)当我们去open时,内核会从文件描述符表中挑选一个最小的未被使用的数字给我们返回。也就是说如果之前fd已经占满了0-9,那么我们下次open得到的一定是10.(但是如果上一个fd得到的是9,下一个不一定是10,这是因为可能前面更小的一个fd已经被close释放掉了)
(5)fd中0、1、2已经默认被系统占用了,因此用户进程得到的最小的fd就是3了。
(6)linux内核占用了0、1、2这三个fd是有用的,当我们运行一个程序得到一个进程时,内部就默认已经打开了3个文件,这三个文件对应的fd就是0、1、2。这三个文件分别叫stdin、stdout、stderr。也就是标准输入标准输出、标准错误
(7)标准输入一般对应的是键盘(可以理解为:0这个fd对应的是键盘的设备文件),标准输出一般是LCD显示器(可以理解为:1对应LCD的设备文件)
(8)printf函数其实就是默认输出到标准输出stdout上了。stdio中还有一个函数叫fpirntf,这个函数就可以指定输出到哪个文件描述符中。

2、常用API

open、close、write、read、lseek

2.1OPEN

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode)

const char *pathname为需要打开的文件、

flags通过一些宏设置读写权限

O_RDONLY、 O_WRONLY 、O_RDWR(只读 只写 读写)

O_APPEND O_APPEND属性去打开文件时,如果这个文件中本来是有内容的,则新写入的内容会接续到原来内容的后面

O_TRUNC  O_TRUNC属性去打开文件时,如果这个文件中本来是有内容的,则原来的内容会被丢弃。

O_CREAT   O_CREAT若不存在则创建。open函数在使用O_CREAT标志去创建文件时,可以使用第三个参数mode来指定要创建的文件的权限。mode使用4个数字来指定权限的,其中后面三个很重要,对应我们要创建的这个文件的权限标志。譬如一般创建一个可读可写不可执行的文件就用0666

O_EXCL  加上O_EXCL如果文件已经被打开则打开失败

O_NONBLOCK 默认为阻塞模式。添加这个设置为非阻塞模式

O_SYNC write阻塞等待底层完成写入才返回到应用层。

2.2 read

  ssize_t read(int fd, void *buf, size_t count);

2.3 write

  ssize_t write(int fd, const void *buf, size_t count);

2.3lseek

    执行read与write函数都会使文件指针移动。lseek函数可以调整文件指针。

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

  参数解释。第一个代表文件描述符、第二个代表移动个数、第三个设置移动头。

   lseek(fd, 0 ,SEEK_SET);//文件指针指向头

   SEEK_SET代表指向头

    SEEK_END代表尾部

   SEEK_CUR代表当前位置

3.3close

  可以通过close关闭打开的文件描述符。

3.4dup和dup2函数

(1)dup系统调用对fd进行复制,会返回一个新的文件描述符(譬如原来的fd是3,返回的就是4)
(2)dup系统调用有一个特点,就是自己不能指定复制后得到的fd的数字是多少,而是由操作系统内部自动分配的,分配的原则遵守fd分配的原则

(3)dup2和dup的作用是一样的,都是复制一个新的文件描述符。但是dup2允许用户指定新的文件描述符的数字。

3.5fcntl的原型和作用

  fcntl函数是一个多功能文件管理的工具箱,接收2个参数+1个变参。第一个参数是fd表示要操作哪个文件,第二个参数是cmd表示要进行哪个命令操作。变参是用来传递参数的,要配合cmd来使用。

4、标准IO库介绍

4.1、标准IO和文件IO有什么区别
(1)看起来使用时都是函数,但是:标准IO是C库函数,而文件IO是linux系统的API
(2)C语言库函数是由API封装而来的。库函数内部也是通过调用API来完成操作的,但是库函数因为多了一层封装,所以比API要更加好用一些。
(3)库函数比API还有一个优势就是:API在不同的操作系统之间是不能通用的,但是C库函数在不同操作系统中几乎是一样的。所以C库函数具有可移植性而API不具有可移植性。
(4)性能上和易用性上看,C库函数一般要好一些。譬如IO,文件IO是不带缓存的,而标准IO是带缓存的,因此标准IO比文件IO性能要更高。

4.2、常用标准IO函数介绍
(1)常见的标准IO库函数有:fopen、fclose、fwrite、fread、ffulsh、fseek

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
int main(int argc , char *argv[])
{
    int fd=-1; //fd 文件描述符
    char buf[100]={0};//字符缓冲区
    char writebuf[20]="ilovezw";//字符缓冲区
    int ret;
    //第一步打开
    //fd = open ("a.txt",O_RDWR|O_APPEND);
    fd = open ("a.txt",O_RDWR);
    if(-1 == fd)
    {
        perror("文件打开错误");
        _exit(-1);
    }
    else
    {
        printf("文件打开成功,fd=%d.\n",fd);
    }
    //lseek(fd, 3 ,SEEK_SET);//光标位移3

    //第二步读写

    ret=write(fd,writebuf,strlen(writebuf));//写函数
    if(-1==ret)
    {
        //printf("write error");
        perror("write error");
        _exit(-1);
    }
    else
    {
        printf("ret=%d\n",ret);
        //lseek(fd, -ret ,SEEK_SET);//光标位移3
    }
    lseek(fd, 0 ,SEEK_SET);//文件指针指向头
    ret=read(fd,buf,20);//读文件
    if(-1==ret)
    {
        //printf("read error");
        perror("read error");
        _exit(-1);
    }
    else
    {
        printf("ret=%d,a.txt=%s\n",ret,buf);
    }
    //第三步关闭
    close(fd);
    return 0;
}
/*标准IO*/

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int main(int argc,char * argv[])
{
    FILE *fp =NULL;
    char buf[10];
    fp = fopen("1.txt","r+");
    if(NULL == fp)
    {
        perror("fopen");
        exit(-1);
    }
    memset(buf,0,sizeof(buf));
    fwrite("12345",1,5,fp);
    fseek( fp, 0, SEEK_SET );
    fread(buf,1,5,fp);
    printf("%s\n",buf);
    fclose(fp);
    return 0;
}
时间: 2024-10-06 09:09:17

linux 文件IO的相关文章

漫谈linux文件IO

原文转自:http://blog.chinaunix.net/uid-27105712-id-3270102.html 在Linux 开发中,有几个关系到性能的东西,技术人员非常关注:进程,CPU,MEM,网络IO,磁盘IO.本篇文件打算详细全面,深入浅出.剖析文件IO的细节.从多个角度探索如何提高IO性能.本文尽量用通俗易懂的视角去阐述.不copy内核代码. 阐述之前,要先有个大视角,让我们站在万米高空,鸟瞰我们的文件IO,它们设计是分层的,分层有2个好处,一是架构清晰,二是解耦.让我们看一下

Linux文件IO(四)IO多路复用

当程序进行IO时,如果数据尚未准备好,那么IO将处于阻塞状态.当某个进程有多个打开的文件,比如socket,那么其后的所有准备好读写的文件将受到阻塞的影响而不能操作.不借助线程,单一进程无法在同一时间服务多个文件描述符.非阻挡式IO可以作为一个解决方案,但是效率并不高.首先进程需要不断发IO请求,其次,如果程序可以休眠,让出CPU将提高效率.多任务式IO是在其中任何一个文件描述符就绪时收到通知,此时IO将不会受到阻挡,其余时间处于休眠状态,将CPU资源让给别的进程.I/O多路复用的设计遵循以下原

linux 文件 IO 目录操作及文件属性

///////////////////////////////////////////////////练习:实现列出某个目录中所有文件属性(文件大小,文件最后修改时间,文件名)//目录名由参数传入 ./dir /home/linux#include <sys/stat.h>#include <dirent.h>#include <stdio.h> int main(int argc, char *argv[]){ DIR *dp; //定义一个结构体变量 打开文件目录,

Linux文件IO

参考<unix高级环境编程> 本章开始讨论U N I X系统,先说明可用的文件I / O函数——打开文件.读文件.写文件等等.大多数U N I X文件I / O只需用到5个函数:o p e n.r e a d.w r i t e.lseek 以及c l o s e.然后说明不同缓存器长度对r e a d和w r i t e函数的影响. 在P O S I X . 1应用程序中,幻数0.1.2应被代换成符号常数S T D I N_ F I L E N O.S T D O U T_ F I L E

Linux文件IO(五)IO内核

Linux内核实现I/O主要在三个内核子系统:虚拟文件系统(VFS),页缓存,和页回写.虚拟文件系统(有时也叫做virtual file switch)是一种Linux内核的文件操作的抽象机制.它允许内核在无需了解文件系统类型的情况下,使用文件系统函数和操作文件系统数据.VFS实现这种抽象的方法是使用一种通用文件模型,它是所有Linux文件系统的基础.基于函数指针和各种面向对象方法,通用文件模型提供了一种Linux内核文件系统必须遵循的框架.它允许VFS对文件系统发起请求.框架提供了钩子来支持读

嵌入式 Linux系统编程(一)——文件IO

嵌入式 Linux系统编程(一)--文件IO 一.文件IO概念 linux文件IO操作有两套大类的操作方式:不带缓存的文件IO操作,带缓存的文件IO操作.不带缓存的属于直接调用系统调用(system call)的方式,高效完成文件输入输出.它以文件标识符(整型)作为文件唯一性的判断依据.这种操作不是ASCI标准的,与系统有关,移植有一定的问题.而带缓存的是在不带缓存的基础之上封装了一层,维护了一个输入输出缓冲区,使之能跨OS,成为ASCI标准,称为标准IO库.不带缓存的方式频繁进行用户态 和内核

Linux下用文件IO的方式操作GPIO(/sys/class/gpio)(转)

通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入.文件IO方式操作GPIO,使用到了4个函数open.close.read.write. 首先,看看系统中有没有"/sys/class/gpio"这个文件夹.如果没有请在编译内核的时候加入 

Linux系统开发 2 文件IO open() close() read() write() perror() lseek() fcntl() ioctl()

[本文谢绝转载,原文来自http://990487026.blog.51cto.com] 大纲 Linux系统开发 man 文档的使用 文件IO open() 创建文件,指定权限位 open() 接收参数 创建文件 open() 传两个参数 第三个参数从内存取垃圾值 write()函数 向文件写数据 write()函数的覆盖操作 open()函数文件的追加 open() 创建文件,如果文件已经存在,就报错 测试一个程序最多能创建1021个文件,3个STDIN STDOUT STDERR已经存在了

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

文件IO操作相关系统编程 这里主要说两套IO操作接口,分别是: POSIX标准 read|write接口,函数定义在#include<unistd.h> ISO C标准 fread|fwrite接口,函数定义在#include<stdio.h> 有书上说POSIX标准与ISO C标准的区别在于文件读写是否带缓冲区,我则不是很认同,因此POSIX标准下的IO操作也是带缓冲区的,至于这两个标准下的IO性能谁更加好则不一定,因为这和缓冲区的大小,以及用户逻辑有很大关系. POSIX标准