linux文件io/系统调用io中的open(),close(),read(),write()函数
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文件描述符的概念
我们知道在Linux系统中一切皆可以看成是文件,文件又可分为:普通文件、目录文件、链接文件和设备文件。在操作这些所谓的文件的时候,我们每操作一次就找一次名字,这会耗费大量的时间和效率。所以Linux中规定每一个文件对应一个索引,这样要操作文件的时候,我们直接找到索引就可以对其进行操作了。
文件描述符(filedescriptor)就是内核为了高效管理这些已经被打开的文件所创建的索引,其是一个非负整数(通常是小整数),用于指代被打开的文件,所有执行I/O操作的系统调用都通过文件描述符来实现。同时还规定系统刚刚启动的时候,0是标准输入,1是标准输出,2是标准错误。这意味着如果此时去打开一个新的文件,它的文件描述符会是3,再打开一个文件文件描述符就是4…
Linux内核对所有打开的文件有一个文件描述符表格,里面存储了每个文件描述符作为索引与一个打开文件相对应的关系,简单理解就是下图这样一个数组,文件描述符(索引)就是文件描述符表这个数组的下标,数组的内容就是指向一个个打开的文件的指针。
一 、open()函数
功能:打开文件。
头文件:
#includ e <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);
返回值:打开成功:返回一个int 型正整数(文件描述符);打开失败:返回 -1; 参数说明:pathname 指向文件路径的字符指针;
flags 文件打开方式 常用选项是:O_RDONLY(只读);O_WRONLY(只写); O_RDWR(可读写);
O_CREAT:文件不存在时,创建该文件, 文件的权限由第三个参数mode决定最终的权限。 mode
当flags选项是O_CREAT时,需要使用mode指定文件权限。 mode: 创建的文件的权限,一般0664
指定文件拥有者,群组用户及其他用户都拥有对文件的读写执行权限。其他相关权限可查阅
flags: 打开方式详细说明
O_RDONLY: 只读打开 O_WRONLY: 只写打开 O_RDWR: 可读写打开 O_CREAT: 当文件不存在时创建文件,此时需要第三个参数mode mode: 创建的文件的权限,一般0664 O_TRUNC: 当文件存在时清空文件内容 O_APPEND: 追加打开
二、close()函数
close函数功能:关闭一个已打开的文件。
#includ e <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
int close(int fd);
返回值:成功返回0,出错返回-1并设置errno
参数fd是要关闭文件描述符。当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close关闭,所以即使用户程序不调用close,在终止时内核也会自动关闭它打开的所有文件。
由open返回的文件描述符一定是该进程尚未使用的最小的描述符。
三、 read()函数
read()函数功能:用来读取打开文件的数据
read()函数
头文件和函数原型
#include <unistd.h>
ssize_t read(int fd, void *buf, size_t count);
// ssize_t 是有符号整数类型;size_t是无符号整数类型
参数
fd: 文件描述符(文件名或文件路径)
buf: 存放输入数据的内存缓冲区地址
count: 指定最多能读取的字节数
返回值
读取成功:返回的是读取到的字节数
读取到文件尾:0
读取失败:-1
1.如果读取成功,则返回实际读到的字节数。这里又有两种情况:一是如果在读完count要求字节之前已经到达文件的末尾,那么实际返回的字节数将小于count值,但是仍然大于0;二是在读完count要求字节之前,仍然没有到达文件的末尾,这是实际返回的字节数等于要求的count值。
2、如果读取时已经到达文件的末尾,则返回0。
3、如果出错,则返回-1。
注意:
比如一个有100个字节的文件,第一次读取10个字节,这时读取指针在第10个字节处。再次进行10个字节的读操作时,会接着第一次读的位置接着往后读。如果还想从开始读,可使用lseek函数定位。
四、write()函数
write()函数功能:将数据写入一个已打开的文件中。
write()函数
头文件与函数原型
#include <unistd.h>
ssize_t write(int fd, const void *buf, size_t count);
参数
与read()函数类似
fd: 文件描述符(文件名或文件路径)
buf: 要写入文件中数据的内存地址
count: 从 buf 写入文件的数据字节数
返回值
写入成功: 返回 实际写入的字节数
写入失败:-1
五、lseek()函数
对于每个打开的文件,系统都会记录它的读写位置偏移量,我们也把这个读写位置偏移量称为读写偏移量,Linux 中可使用系统函数 lseek 来修改文件偏移量 ( 读写位置 )
函数代码
#include <sys/types.h>
#include <unistd.h>
off_t lseek(int fd, off_t offset, int whence);
参数
fd: 文件描述符。
offset: 偏移量,以字节为单位。
whence: 用于定义参数 offset 偏移量对应的参考值,该参数为下列其中一种(宏定义):
SEEK_SET:读写偏移量将指向 offset 字节位置处(从文件头部开始算);
SEEK_CUR:读写偏移量将指向当前位置偏移量 + offset 字节位置处, offset 可以为正、也可以为负,如果是正数表示往后偏移,如果是负数则表示往前偏移;
SEEK_END:读写偏移量将指向文件末尾 + offset 字节位置处,同样 offset 可以为正、也可以为负,如果是正数表示往后偏移、如果是负数则表示往前偏移。
返回值:成功将返回从文件头部开始算起的位置偏移量(字节为单位),也就是当前的读写位置;发生错误将返回-1,并设置errno值。
程序演示
程序实现:文件内容copy
1 #include <stdio.h>
2 #include<stdlib.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 int main(int varg,char **vary)
8 {
9 char buffer[1024];//定义一个数组来存储读取到的数据
10 if(varg < 3)
11 {
12 fprintf(stderr,"输入的参数不够,请输入三个参数");
13 }
14 int ps,pr,n;
15 ps= open(vary[1],O_RDONLY);//已只读的形式打开第一个文件,将打开的文件描述符赋值给ps
16 /*打开第二个文件 如果没有则创建文件创建文件的执行权限(八进制:0644)为-rw-r-r,打开文件之后将文件内容清空 */
17 umask(0000);
18 pr= open(vary[2],O_WRONLY|O_CREAT,O_TRUNC,0644);
19 while((n=read(ps,buffer,1024))>0)//一次从文件中读取1024个字节并存储到buffer中,n大于0则说明文件内容还未读取完
20 {
21 write(pr,buffer,n);
22 }
23 close(ps);
24 close(pr);//关闭打开的两个文件
25 }
~