1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Linux 系统应用编程——文件I/O

Linux 系统应用编程——文件I/O

时间:2019-07-07 20:27:28

相关推荐

Linux 系统应用编程——文件I/O

Linux操作系统是基于文件概念的。文件是以字符序列构成的信息载体。根据这一点,可以把I/O设备当做文件来处理,因此,在磁盘上的普通文件进行交互所用的统一系统调用可以直接用于I/O设备。这样大大简化了系统对于不同设备的处理,提高了效率。Linux中的文件主要分为6种:普通文件、目录文件、符号链接文件、管道文件、套接字文件和设备文件。

那么,内核如何区分和引用特定的文件呢?这里用到了一个重要的概念——文件描述符。对于Linux而言,所有的设备和文件的操作都是通过文件描述符来进行的。文件描述符是一个非负的整数,它是一个索引值,并指向在内核中每个进程打开文件的记录表。当打开一个现存文件或创建一个新文件时,内核就向进程返回一个文件描述符;读写文件时,需要把文件描述符作为参数传递给相应的函数。

通常,一个进程启动时,都会打开3个流:标准输入、标准输出和标准错误。这3个流分别对应文件描述符0、1 和 2(对应的宏分别是STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO)。

基于文件描述符的I/O操作虽然不鞥直接移植到类Linux以外的系统上去(如Windows),但它往往是实现某些I/O操作的唯一途径,如Linux中底层文件操作函数、多路I/O、TCP/IP套接字编程接口等。同时,他们也很好地兼容POSIX标准,因此,可以很方便地移植到任何POSIX平台上。基于文件描述符的I/O操作是Linux中最常用的操作之一。

文件I/O相关函数:open() 、read() 、write() 、lseek() 和close() 。这些函数的特点是不带缓冲,直接对文件(包括设备)进行读写操作。这些函数不是ANSI C的组成部分,而是POSIX相关标准来定义。

1、文件打开与和关闭

open()函数用于创建或打开文件,在打开或创建文件时可以指定文件打开方式及文件的访问权限。

函数原型如下:

[cpp]view plaincopy#include<sys/stat.h> #include<fcntl.h> intopen(constchar*pathname,intflags,intperms);

1)pathname: 被打开的文件名(可包括路径名)

2)flags(文件打开方式,这里介绍几个常用的)

O_RDONLY只读

O_WRONLY只写

O_RDWR可读可写

这三者必有其一

O_CREAT如果文件不存在,就创建一个新文件,并用第三个参数为其设置权限;

O_TRUNC若文件已经存在,那么会删除文件中的全部原有数据,并且设置文件大小为0;

O_APPEND以添加方式打开文件,在写文件时,文件读写文职自动指向文件的末尾,即将写入的数据添加到文件的末尾;

3)perms 新建文件的存取权限

close()函数用于关闭一个被打开的文件。当一个进程终止时,所有打开的文件都有内核自动关闭。很多程序都利用这一特性而不显示地关闭一个文件。

函数原型:

[cpp]view plaincopy#include<unistd.h> intclose(intfd);

2、文件读写

read()函数从文件中读取数据存放到缓冲区中,并返回实际读取的字节数。若返回0,则表示没有数据可读,即已达到文件尾。读操作从文件的当前读写位置开始读取数据,当前读写位置自动往后移动。

函数原型:

[cpp]view plaincopy#include<unistd.h> ssize_tread(intfd,void*buf,size_tcount);

函数传入值:

fd 文件描述符;

buf 指定存储器读取数据的缓冲区;

count 指定读出的字节数;

函数返回值:

成功:读到的字节数;

0:已到达文件尾;

-1:出错;

在读到普通文件时,若读到要求的字节数之前已到达问价你的尾部,则返回的字节数会小于指定读出的字节数;

write()函数将数据写入文件中,并返回实际写入的字节数。写操作从文件的当前读写位置开始写入。对磁盘文件进行写操作时,若磁盘已满,write()函数返回失败;

函数原型:

[cpp]view plaincopy#include<unistd.h> ssize_twrite(intfd,void*buf,size_tcount);

函数传入值:

fd 文件描述符

buf 指定存储器写入数据的缓冲区

count 指定读出的字节数

函数返回值:

成功:已写的字节数

-1:出错

下面写个简单小程序,实现copy程序,完成文件的复制,代码如下:

[cpp]view plaincopy#include<stdio.h> #include<unistd.h> #include<sys/types.h> #include<fcntl.h> #include<sys/stat.h> #definemaxsize256 intmain(intargc,char*argv[]) { intfd1,fd2; intbyte; charbuffer[maxsize]; if(argc!=3) { printf("commanderror!\n"); return-1; } if((fd1=open(argv[1],O_RDONLY))==-1) { perror("openfails"); return-1; } if((fd2=open(argv[2],O_WRONLY|O_CREAT|O_TRUNC,0664))==-1)//如果文件不存在,则创建,若存在,则覆盖; { perror("openfails"); return-1; } while(1) { if((byte=read(fd1,buffer,maxsize))>0) write(fd2,buffer,byte); if(byte==0) break;//如果读不到数据,则返回 } close(fd1); close(fd2); return0; }

执行结果如下:

[cpp]view plaincopyfs@ubuntu:~/qiang/fileIO/open$ls-l total16 -rwxrwxr-x1fsfs7388Jan416:18cp -rw-rw-r--1fsfs625Jan416:18cp.c -rw-rw-r--1fsfs526Jan416:01file1.c fs@ubuntu:~/qiang/fileIO/open$./cpfile1.cfile2.c fs@ubuntu:~/qiang/fileIO/open$ls-l total20 -rwxrwxr-x1fsfs7388Jan416:18cp -rw-rw-r--1fsfs625Jan416:18cp.c -rw-rw-r--1fsfs526Jan416:01file1.c -rw-rw-r--1fsfs526Jan416:19file2.c fs@ubuntu:~/qiang/fileIO/open$

我们可以看到,原来file2.c并不存在,执行完程序后,file2.c存在,且大小和file1.c相同;

3、文件定位

lseek()函数对文件当前读写位置进行定位。它只能对可定位(可随机访问)文件操作。管道、套接字和大部分字符设备文件不支持此类操作;

函数原型:

[cpp]view plaincopy#include<unistd.h> #include<sys/types.h> off_tlseek(intfd,off_toffset,intwhence);

函数传入值:

fd 文件描述符

offset 相对于基准点whence 的偏移量。以字节为单位,正数表示向前移动,负数表示向后移动

whence 当前位置的基点

SEEK_SET:文件的起始位置

SEEK_CUR:文件当前读写位置

SEEK_END:文件的结束位置

函数的返回值:

成功:文件当前读写位置

-1:出错

我们可以通过lseek函数实现一个小功能:查看文件的大小,代码如下:

[cpp]view plaincopy#include<stdio.h> #include<unistd.h> #include<fcntl.h> #include<sys/stat.h> #include<sys/types.h> intmain(intargc,constchar*argv[]) { intfd; intlength; if(argc!=2) { printf("commanderror!\n"); return-1; } if((fd=open(argv[1],O_RDONLY))==-1) { perror("openfails"); return-1; } length=lseek(fd,0,SEEK_END); printf("Thelengthof%sis%dbytes!\n",argv[1],length); return0; }

执行结果如下:

[cpp]view plaincopyfs@ubuntu:~/qiang/fileIO/lseek$ls-l total12 -rwxrwxr-x1fsfs7308Jan416:47lseek -rw-rw-r--1fsfs424Jan416:46lseek.c fs@ubuntu:~/qiang/fileIO/lseek$./lseeklseek.c Thelengthoflseek.cis424bytes! fs@ubuntu:~/qiang/fileIO/lseek$

我们可以看到,得到了lseek.c正确大小!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。