linux文件I/O教程(1)

一,文件描述符

对内核而言,所以打开的文件都通过文件描述符引用。每位进程都有一些与之关联的文件描述符。文件描述符是一个非负整数。当打开一个现有文件或创建一个新文件时,内核向进程返回一个文件描述符。当读或写一个文件时,使用open或creat返回的文件描述符标示该文件,将其作为参数传送给read和write。

通常有三个以及打开的文件描述符,她们是:

复制代码

代码如下:

0:标准输入STDIN_FILENO

1:标准输出STDOUT_FILENO

2标准错误输出STDERR_FILENO

每行前面的符号常量是依从POSIX而定的。

open函数

复制代码

代码如下:

#include

#include

#include

intopen(constchar*pathname,intflags);

intopen(constchar*pathname,intflags,mode_tmode);

pathname是要打开或创建文件的名子。

flag拿来定义打开文件所采取的的动作linux系统有哪几种文件类型,必须调用以下模式之一

O_RDONLY,O_WRONLY,O_RDWR分别代表只读,只写,读写方法打开。

open还可以包括以下可选模式的组合

O_APPEND:把写入数据追加到文件的尾端

O_CREAT:若文件不存在,则创建它。使用此选项时,须要第三个参数modelinux系统有哪几种文件类型,用其指定该新文件的访问权限。

O_EXCL:假如同时指定了O_CREAT,而文件存在,则会出错。用此可以测试一个文件是否存在,假如存在,则创建文件,这使测试和创建三者成为一个原子操作。

O_TRUNC:假若此文件存在,并且为只写或读写成功打开,则将其厚度截为0。

open返回的文件描述符一定是最小的未用描述符数值。这一点被个别应用程序用在标准输入,标准输出或标准错误输出上。如,一个程序关掉了自己的标准输出,之后再度调用open,文件描述符1都会被调用,但是标准输出将被有效的重定向到另一个文件或设备。

POSIX规范还标准化了一个creat调用,此函数等效于

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

close函数

#include

intclose(intfd);

close调用中止一个文件描述符fd与对应文件之间的关联。文件描述符被释放后并能重新使用。close调用成功返回0红帽linux系统下载,出错返回-1.

关掉一个文件时会释放该进程加在文件上的所有记录锁。当一个进程中止时linux源代码分析,内核手动关掉它所有打开的文件。

lseek函数

每位打开的文件都有一个与其相关联的”当前文件偏斜量”。按系统默认情况,当打开一个文件时,除非指定O_APPEND选项,否则该偏斜量被设置为0。lseek可以为一个打开的文件设置偏斜量。

复制代码

代码如下:

#include

#include

off_tlseek(intfd,off_toffset,intwhence);

offset拿来指定位置,whence参数定义该偏斜值的用法。whence可取以下值:

复制代码

代码如下:

SEEK_SET:Theoffsetissettooffsetbytes.

SEEK_CUR:Theoffsetissettoitscurrentlocationplusoffsetbytes.

SEEK_END:Theoffsetissettothesizeofthefileplusoffsetbytes.

成功调用返回从文件头到文件表针被设置处的字节偏斜值,失败返回-1。参数offset定义在中。

当偏斜量小于文件厚度时,出现空洞,空洞不占用储存区。

read函数

复制代码

代码如下:

#include

ssize_tread(intfd,void*buf,size_tcount);

将与文件描述符fd关联的文件中读入count个字符放在buf中。返回读入的字节数,它可能大于恳求的字节数。假如read调用返回0,就表示未读入任何数据,已抵达了文件尾。返回-1,就表示出错。

write函数

复制代码

代码如下:

#include

ssize_twrite(intfd,constvoid*buf,size_tcount);

把缓冲区buf的前count个字节写入与文件描述符fd相关联的文件中。返回实际写入的字节数,一般与count值相同;否则表示出错。出错的一个常见诱因是:c盘已写满,或则超出了一个给定进程的文件宽度限制。

实例:创建一个文件,写入数据,联通当前偏斜量,在读数据。

复制代码

linux系统有哪几种文件类型_linux系统有哪几种文件类型_linux系统有哪几种文件类型

代码如下:

#include//必须最早出现,由于它可能会影响到其他头文件。#include

#include

#include

#include

intmain()

char*filename=".//file";

charbuf[100];

charbuf1[5];

intfd;

printf("openafiletowriten");

if((fd=open(filename,O_RDWR|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH))==-1)

perror("cannotopenfilen");

return1;

printf("openfilesuccessfully!n");

printf("inputastring:");

gets(buf);

//writeintofile

if(write(fd,buf,strlen(buf))!=strlen(buf))

perror("cannotwriteintofilen");

return1;

close(fd);

printf("openfiletoread.n");

if((fd=open(filename,O_RDONLY))==-1)

perror("cannotopenthefile.n");

return1;

if(lseek(fd,3,SEEK_SET)==-1)

perror("lseekerroen");

return1;

//readfromthefile

if(read(fd,buf1,4)==-1)

linux系统有哪几种文件类型_linux系统有哪几种文件类型_linux系统有哪几种文件类型

perror("readerror.n");

return1;

printf("readfromfileis%sn",buf1);

close(fd);

return0;

执行与输出结果:

复制代码

代码如下:

root@jb51:~$gcc-oioio.c

root@jb51:~$./io

openafiletowrite

openfilesuccessfully!

inputastring:akxivbaslzkncxcasbxbwwvaidxbd

openfiletoread.

readfromfileisivba

linux文件I/O教程(2)

下边介绍了linux中有关文件I/O的相关内容,内核使用三种数据结构表示打开的文件,她们之间的关系决定了在文件共享方面一个进程对另一个进程可能形成的影响。

一,文件共享

内核使用三种数据结构表示打开的文件,她们之间的关系决定了在文件共享方面一个进程对另一个进程可能形成的影响。

1)每位进程在进程表中都有一个记录项,记录项中包含一张打开文件描述表,可将其视为一个矢量,每位描述符占用一项。与每位文件描述符相关联的是:

a)文件描述符标志

b)指向一个文件表项的表针

2)内核为所有打开文件维持一张文件表。每位文件表项包含:

a)文件状态标志(读、写、读写、添些、同步和阻塞等)

b)当前文件偏斜量

c)指向文件v节点表项的表针

3)每位打开文件(或设备)都有一个v节点(v-node)结构。v节点包含了文件类型和对比文件进行各类操作的函数的表针。对于大多数文件,v节点还包含了该文件的i节点。i节点包含文件所有者、文件厚度、文件所在的设备、指向文件实际数据块在c盘上所在位置的表针等。

打开文件的内核数据结构

假如两个进程各自打开了同一个文件,则如图2所示。假设第一个进程在文件描述符3打开上该文件,而另一个进程在文件描述符4上打开该文件。每位进程都得得到一个文件表项,但对一个给定的文件只有一个v节点表项。每位进程都有自己的文件表项的一个理由是:使每位进程都有自己对该问价的当前偏斜量。

现今对前一节文件I/O(1)的几个操作进一步说明:

1.完成write以后,文件中当前偏斜量即所降低的字节数。假如当前偏斜量小于文件宽度,则将i节点中当前文件厚度设为当前文件偏斜量。

linux系统有哪几种文件类型_linux系统有哪几种文件类型_linux系统有哪几种文件类型

2.用O_APPEND打开一个文件,相应标志会被设置到文件状态标示中。每次写时,当前偏斜量会被设置为i节点中的文件宽度

3.lseek定位到文件尾端时,则文件当前偏斜量会被设置为当前文件厚度。

可能有多个文件描述符指向同一文件表项。调用dup和fork时都能看见这一点。

多个进程读同一文件能正确工作。但多个进程写同一文件时,可能形成预期不到的后果。可以借助原子操纵防止此类情况。

原子操作

通常而言,原子操作指的是由多部组成的操作。假如该院自地执行,要么执行完所以步骤,要么一步也不执行。

1.添加至一个文件

考虑一个进程,它要讲数据添加到一个文件尾端。初期UNIX不支持open,所以可以如下实现:

复制代码

代码如下:

if(lseek(fd,0L,2)err_sys(“lseekerror”);

if(write(fd,buf,100)!=100)

err_sys(“writeerror”);

对于单个进程,这段程序能正常工作。但多个进程就不一定。结社进程A和B都对同一文件进行添加操作。每位进程都打开该文件,此时数据结构之间关系如图2中所示。假设A调用lseek,将A的当前偏斜量设置为1500。进程B执行lseek也将其当前偏斜量设为1500。之后B调用write,将当前偏斜量增至1600。之后内核又进行进程切换使进程A恢复运行,当A调用write时,从其当前偏斜量1500处将数据写入,将替换B刚写入到该文件中的数据。

问题出在逻辑操作“定位到文件尾端处,之后写“使用了两个分开的函数调用。解决办法是使这两个操作成为一个原子操作。O_APPEND标示,使内核每次对文件进行写之前,都将进程当前偏斜量设置到该文件的尾端处。

2.pread和pwrite函数

原子性地定位搜索和执行I/0。

复制代码

代码如下:

#include

ssize_tpread(intfd,void*buf,size_tcount,off_toffset);

ssize_tpwrite(intfd,constvoid*buf,size_tcount,off_toffset);

ssize_tpread(intfd,void*buf,size_tcount,off_toffset);

ssize_tpwrite(intfd,constvoid*buf,size_tcount,off_toffset);

dup和dup2函数

复制代码

代码如下:

#include

intdup(intoldfd);

intdup2(intoldfd,intnewfd);

前面两个函数都可拿来复制一个现存的文件描述符。

由dup返回的新文件描述符一定是当前可用文件描述符中的最小数值。用dup2则可以用newfd参数指定新描述符的数值。假如newfd早已打开,则先将其关掉。假如newfd等于oldfd,则dup2返回newfd而不关掉它。

图3.3显示了这些情况。

假设我们的进程执行了:

newfd=dup(1);

当此函数执行时,假定下一个可用的描述符是3。由于这两个描述符指向同一个文件表项,所以她们共享文件标志以及同一文件偏斜量。

sync、fsync和fdatasync

复制代码

代码如下:

#include

voidsync(void);

intfsync(intfd);

intfdatasync(intfd);

当将数据写入文件时,内核一般将数据复制到一个缓冲区,直至缓冲区写满,再将缓冲区排路输出队列,之后等待其抵达队首,才进行实际的I/O操作。这些输出消暑被称为延后写。延后写降低了c盘的读写次数,但却增加了文件内容的跟新速率。当系统发生故障时,延后写可能导致文件跟新内容的遗失。为了保证c盘上实际文件系统与缓冲区高速缓存中内容一致性,UNIX系统提供了sync、fsync和fdatasync三个函数。

fcntl函数

复制代码

代码如下:

#include

#include

intfcntl(intfd,intcmd,.../*arg*/);

可以改变早已打开文件的性质。

复制一个现有的描述符(cmd=F_DUPFD)

获得或设置文件描述符(cmd=F_GETFD|F_SETFD)

获得或设置文件状态标志(cmd=F_GETFL|F_SETFL)

获得或设置异步I/O所有权(cmd=F_GETOWN|F_SETOWN)

获得或设置记录锁(cmd=F_GETLK|F_SETLK、F_SETLKW)

可以用fcntl函数设置文件状态,常用设置套接字描述符为非阻塞O_NONBLOCK

ioctl函数

#include

intioctl(intd,intrequest,...);

提供了一个用于控制设备及其描述符行为和配置底层服务的插口。

/dev/fd

打开文件/dev/fd/n等效于复制描述符n。

本文原创地址:https://www.linuxprobe.com/lwjijcywjmsf.html编辑:刘遄,审核员:暂无