Linux之文件I/O编程

一、系统调用和API

在Linux中,为了保护内核空间,将程序的运行空间分成了内核空间和用户空间(内核态和用户态),它们运行在不同的级别上。逻辑上是相互隔离的。通常情况下,用户进程是允许访问内核的数据,也没有办法直接调用内核函数。只能在用户空间操作用户数据、调用用户空间的函数。

操作系统为用户提供了两个接口:

1、用户编程接口API:用户利用这些操作命令来组织和控制任务的执行和管理计算机系统。

2、系统调用:请求操作系统提供服务。利用软中断机制向内核提交请求,来获得内核服务的接口。进行系统调度的时候:程序运行空间从用户空间进入内核空间,处理完后再返回用户空间。最基本和最有用的部分(进程控制、文件系统控制、系统控制、内存管理、网络管理、socket控制、用户管理和进程间通信8大模块)

实际上,程序员调用的通常是API。用户可以使用API函数来调用相对应的系统调用。并不是所有的函数都一一对应一个系统调用。存在一个API函数需要几个系统调用来共同完成函数的功能,甚至还有一些API函数不需要调用相对应的系统调用。

在Linux中,用户编程接口(API)遵循了POSIX标准。这是由IEEE和ISO/IEC共同开发的标准系统。该系统是基于当时现有的UNIX实践和经验,描述了操作系统的系统调用编程接口(API),用于保证应用程序可以在源代码一级的多种操作系统上移植运行。这些系统调用编程接口是通过C库(libc)实现的。

系统命令实际上是一个可执行程序。它的内部引用了用户编程接口来实现相应的功能。最终可能还会需要系统调用来完成相应的功能。

二、Linux中的文件和文件描述符

文件的类型:普通文件、目录文件、链接文件、设备文件

文件描述符:1、这是一个非负的整数,是一个索引值,指向内核中每个进程打开文件的记录表。                        用户程序是无法直接访问的。

                      2、当打开一个现存文件或者时创建一个新文件,内核就会向进程返回一个文件描述                        符。当需要读/写文件时,需要将文件描述符作为参数传递给相对应的函数。

例如:

一个进程启动的时候都会打开三个文件:标准输入、标准输出、标准出错处理。

这三个文件相对应的文件描述符分别是:0、1、2(也就是宏替换STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO)

2.1基本文件操作

Linux的输入/输出(I/O)操作,通常为5个方面

                             打开、读取、写入、定位、关闭

对应的系统调用:open、read、write、lseek、close    (不带缓冲区的I/O操作)

这写函数属于POSIX(可移植操作系统接口)的一部分。

函数原型:

#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
int open(const char * pathname,int flags,mode_t mode);
ssize_t read(int fd,void * buf,size_t nbytes);
ssize_t write(int fd,void const void * buf,size_t nbytes);
off_t lseek(int fd,off_t offset,int whence);
int close(int fd);

参数fd是文件描述符。

2.1.1open函数

如果打开的文件不存在,则会创建你要打开的文件。

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

 参数解释:

pathname      是字符串,表示打开的文件名称,可以包含路径

flags               文件的打开方式,可以通过“|”组合构成。O_RDONLY、O_WRONLY、                                   O_RDWR  这三种方式互斥不能同时使用。

mode              被打开文件的存取权限模式。

函数返回值      成功返回文件描述符,不成功返回-1

 

 2.1.2read和write函数

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

参数解释:

fd          文件描述符

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

count      指定读出或写入的字节数

函数返回值: 如果发生错误,返回值为-1,同时设置error变量为错误代码。

                       如果成功,返回值是实际读取或写入的字节数,这个字节数可能小于count。

                     对于读操作:当文件所剩的字节数少于count时,会出现上述的情况

                     对于写操作:当磁盘已满或者某些别的问题时,也会存在这个情况

由于每次读/写的字节数是可以设定的。使用这两个函数时,尽量采取块读/写的方式,而不是每次读取/写入一个字节,这样可以提高I/O的效率。

 

2.1.3close函数

close会让缓冲区中的数据写回磁盘,并释放文件所占的资源。

int close(int fd);

 参数

fd             文件描述符

函数返回值:  若文件顺路关闭,返回值为0

                         若文件关闭失败,返回-1,并且置errno

关闭通过网络访问的文件时会有大概率发生文件关闭错误的情况。

标准I/O操作

因为不带缓冲区的I/O操作效率不高。

ANSI制定一系列基于流缓冲的标准I/O函数。这些函数一般存在C语言标准库的<stdio.h>头文件中

三种不同类型流的相同操作

1、printf()针对标准流

2、fprintf()针对文件流

3、sprintf()针对字符流 

 fopen()函数

打开文件由3个标准函数:fopen、fdopen、freopen

#include<stdio.h>
FILE * fopen(const char* pathname,const char* type);
FILE * freopen(const char*pathname,const char* type,FILE *fp);
FILE * fdopen(int filedes,const char*type);

 它们以不同的模式打开,并返回一个指向文件流的FILE指针,此后对文件读/写都是通过这个FILE指针来进行。

每个文件流都和一个底层文件描述符相关联,可以把底层的输入/输出操作与高层的文件流操作混在一起使用。最好不要这么做,因为数据缓冲的后果是难以预料的。

fopen() 函数可以指定打开的路径和模式,参数pathname相当于open()函数中的标志位flag

type取值类型如下:

 

带有b字符的,例如:rb、r+b等,打开的文件是二进制文件。

fdopen()函数会将参数fd的文件文件描述符转换为对应的文件指针后返回。

freopen()函数会将已打开的文件指针stream关闭后,打开参数pathname的文件。 

fclose()函数

int fclose(FILE *fp);

这时缓冲区的数据将写入文件中,并释放系统所提供的文件资源。

fflush()  这个函数可以实现只将缓冲区的数据写入文件,但是没有关闭文件。

int fflush(FILE *fp); 

fread和fwrite函数 

#include<stdio.h>
size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream);
size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream);

 返回值:读或写的记录数。成功时的记录数等于nmemb,出错或读到文件末尾返回的记录数小于nmemb,也可能返回0。

这两个函数是用来读/写记录。这里的记录是指一串固定长度的字节,例如:一个int,一个结构体、或者一个定长数组。

参数:

size :指出一条记录的长度。

nmemb:指出读/写多少条记录。fread和fwrirte返回的记录数由可能小于nmemb指定的记录数。

              例如:如果当前文件读/写位置按文件末尾只有一条记录的长度,调用fread时指定nmemb为2,但返回的值是1。

                        如果当前读/写位置已经在文件末尾了,或者读文件时出错了,则fread返回0.                          如果写文件时发生错误了,则fwrite的返回值小于nmemb指定的值。

ptr :将上述的记录在ptr所指的内存空间中连续存放。一共:size*nmemb个字节。fread从文件stream中读出size*nmemb字节保存在ptr中,fwrite把ptr中的size*nmemb字节写到文件stream中 

 

 

  • 46
    点赞
  • 34
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值