宝哥软件园

Linux系统中的函数文件操作教程

编辑:宝哥软件园 来源:互联网 时间:2021-08-17

类型:电子数据大小:768KB语言:中文评分:10.0标签:立即下载文件是linux中的一个重要概念。在Linux中,所有东西(几乎所有东西)都是一个文件。简单来说,C语言中基本的printf()函数和scanf()函数实际上都是文件操作。

虽然所有的文件操作都是通过函数调用来实现的,但是它们仍然可以分为两类:系统调用和库函数。

本文将首先介绍Linux中文件、系统调用和库函数的概念,然后详细讨论文件操作的两种方式。

博文的主要内容如下:

Linux中的文件

文件访问-库函数

文件访问-系统调用

内置功能

标准输入输出库

//proc文件系统

Linux中的1个文件

1.1概念

按照通常的定义,一个文件只是一堆数据,内存中是0101。我们在这里讨论的文件有一个更广泛的定义。对于Linux中的文件,我的理解是:

Linux中的文件具有以下特点:可以通过操作系统或程序向外部提供信息或向内部输入信息,可以创建和删除。

在Linux中,文件意义重大,它们为操作系统和设备提供了一个简单统一的接口。在Linux中,几乎所有的东西都可以看作是一个文件。

这意味着普通程序可以像文件一样使用磁盘文件、串口、打印机等设备(通用定义)。

硬件设备在linux操作系统中也表示为文件。例如,可以通过以下命令将cd-rom驱动器装载为文件。

# mount-t iso 9660/dev/hdc/mnt/cdrom

#cd /mnt/rom

然后,你可以像访问普通文件一样在光盘目录中漫游。

1.2操作

就像一般意义上的操作文件一样,linux中的操作文件只需要五个基本功能:

打开、关闭、读取、写入和锁定

通过调用这些函数,您可以在Linux中读写文件。但是,这个操作分为系统调用和库函数调用。简单来说,系统调用是最直接的方式。

库函数调用最终通过系统调用实现。可以认为库函数调用是对系统效率的优化。

关于库函数调用和系统调用的区别和联系,请参考:linux系统调用和库函数调用的区别

我们可以用很少的功能访问和控制文件和设备。这些函数称为系统调用,由操作系统直接提供。它们是操作系统本身的接口。

操作系统的核心部分,内核,实际上是一组设备驱动程序。这些是控制硬件的一些接口。

2文件访问-系统调用

通过系统调用访问文件是最直接的方式。系统调用函数直接作用于操作系统内核的设备驱动,实现文件访问。

2.1文件描述符

系统中要处理的文件(读写操作)需要一个标识符,这样就可以在其他地方识别文件,从而生成文件描述符。文件描述符是小整数,简单来说

文件id用于唯一标识系统中的文件。文件描述符的总数是系统可以打开的最大文件数,具体取决于系统的配置。

当程序开始运行时,也就是系统开始运行时,它通常有三个打开的文件描述符。它们是:

0:标准输入

1:标准输出

2.标准误差

其他文件的文件描述符,在调用文件打开函数打开时返回。也就是说,每个设备对应一个文件描述符。文件描述符由操作系统分配,一次分配最小的一个。

2.2编写系统调用

写,即把缓冲区中的数据写入文件。请注意,这里的文件是广义的文件,如写入磁盘、写入打印机等。

Linux中write()的功能原型;

size_t write(int fildes,const void *buf,size _ t nbytes);

参数描述:

Fildes:文件描述符,标识要写入的目标文件。例如,fildes的值为1,就像用标准输出写数据一样,即在显示屏上显示数据;如果是2,您要标记错误的写入数据。

*buf:要写入的文件,它是一个字符串指针。

Nbytes:要写入的字符数。

函数返回值:size_t返回成功写入文件的字符数。需要指出的是,write可能会报告他写的字节比您请求的少。这不一定是个错误。在程序中,您需要检查

错误发现错误,然后再次调用write来写入剩余数据。

请参见以下示例:

运行结果:

该程序仅在标准输出上显示一条消息。

读取系统调用

系统调用读取从文件中读取数据。要读取的文件由文件描述符标识,数据被读入预定义的缓冲区。他返回实际读入的字节数。

Linux中读取的功能原型;

size_t read(int fildes,void *buf,size _ t nbytes);

参数描述:

Fildes:文件描述符,标识要读取的文件。如果为0,则从标准输入读取数据。功能类似于scanf()。

*buf:用于存储读入数据的缓冲区。

Nbytes:要读取的字符数。

返回值:size_t返回成功读取的字符数,可能小于请求的字节数。

运行结果:

开放系统调用

系统调用open的功能是打开一个文件并返回该文件的描述符。

简单地说,open建立了文件或设备的访问路径。如果操作成功,它将返回一个文件描述符,系统调用(如读写)使用该描述符来比较文件或

要操作的设备。此文件描述符是唯一的,不会与任何其他正在运行的进程共享。如果两个程序同时打开一个文件,他们会得到两个不同的投标描述符。如果

同时操作两个文件,它们独立操作,相辅相成,互相覆盖(先写后盖,先写后写)。为了防止读写冲突,可以使用文件锁定功能。这不是

这个重点后面会介绍。

Linux中有两个open的原型函数:

int open(const char *path,int of lags);

int open(const char *path,int oflags,mode _ t mode);

参数描述。

路径:要打开的文件或设备的名称。

Oflags:表示要打开的文件的访问模式。开放调用必须指定以下文件访问模式之一:

开放调用ha可以在oflags参数中包含以下可选模式的组合(使用“按位”或“运算”):

O_APPEDN:将写数据追加到文件的末尾。

O _ TRUNC:将文件长度设置为零,并丢弃后面的内容。

O_CREAT:如有必要,根据参数模式中给出的访问模式创建一个文件。

O _ EXCL:与O_CREAT一起调用,以确保调用方创建文件。使用这种模式可以防止两个程序同时创建一个文件。如果文件已经存在,打开的调用将失败。

关于其他可能的量程值,请参考open的通话手册。

模式:

当使用O_CREAT标志的open创建文件时,我们必须使用带有三种参数格式的open调用。第三个参数模式是在几个标志按位“或”后获得的。它们是:

S_IRUSR:读取权限,文件所有者。

S_IWUSR:写权限,文件所有者。

S_IXUSR:执行权限,文件所有者。

S_IRGRP:读取权限,文件所属的组。

S_IWGRP:写权限,文件所属的组。

请参见以下示例:

打开(' myfile ',O_CREAT,S _ IRUSR | S _ IXOTH

他的任务是创建一个名为myfile的文件。文件的所有者拥有读取权限,而其他用户拥有执行权限,并且只有这些权限。

运行结果:

该程序创建了一个名为myfile的文件,其所有者拥有读取权限,其他用户拥有执行权限,并且只有这些权限。

关闭系统调用

Close系统调用用于“关闭”文件,close调用终止文件描述符文件及其文件间的关联。文件描述符被释放,可以重用。

关闭成功返回1,错误返回-1。

# Includeunistd.h

int close(int fildes);

Ioctl系统调用

Ioctl为控制设备及其描述符的行为和配置底层服务提供了一个接口。终端、文件描述符,甚至磁带驱动器都可以为它们定义ioctl,特别是

详见具体设备使用说明书。

以下是ioctl的功能原型

# includeunistd.h

int ioctl(int fildes,int cmd、);

Ioctl对描述符fildes指定的对象执行cmd参数中给出的操作。

与文件管理相关的其他系统调用

还有许多其他系统调用可以对文件进行操作。

几个常用的,比如lseek(),设置文件描述符fildes指定的文件的读写指针,也就是可以设置文件的下一个读写位置。

Fstat、stat、lstat和LSTAT是与文件描述符相关的函数操作,这里就不介绍了。

Dup,dup2系统调用。Dup提供了一种复制文件描述符的方法,它使我们能够通过两个或多个不同的文件描述符来访问同一个文件。这可用于

在文件的不同位置读写数据。

4库函数

在输入输出操作中,直接使用系统调用的效率会很低。具体有两个原因:

系统调用会影响系统性能。与函数调用相比,系统调用的开销较大。因为在执行系统调用时,需要切换到内核代码区执行,然后返回用户代码。这不可避免地需要大量的时间和支出。一种解决方案是最小化系统调用的数量,让每个系统调用完成尽可能多的任务。例如,每个系统调用都会写入大量字符,而不是单个字符。

一旦系统调用,硬件将限制可以读写的数据块。例如,磁带机通常的写入块长度为10k。如果缩写数据不是10k的整数倍,磁带机仍将以10k为单位缠绕磁带,在磁带上留下间隙。

为了提高文件访问操作的效率,使文件操作更加方便,Linux发行版提供了一系列标准函数库。它们是函数的集合,您可以在自己的程序中方便地使用。

操纵文件。提供输出缓冲的标准输入输出库就是一个例子。您可以有效地编写任何长度的数据块,并且库函数在必要时安排底层函数调用(系统调用)

也就是说,库函数在用户和系统之间增加了一个中间层。如下图所示:

库函数是根据实际需要打包的系统调用,用户可以在程序中方便地使用库函数,比如标准的I/O库(后面会介绍)

5标准输入/输出库

标准输入输出库及其头文件stdio.h为底层输入输出系统调用提供了通用接口。这个库现在已经成为ANSI标准C的一部分,但是前面提到的系统调用不是。

标准I/O库为打印格式和扫描输入提供了很多复杂的功能,同时也负责满足设备的缓冲需求。

在许多方面,使用标准输入/输出库类似于使用底层文件描述符。需要先打开一个文件,并且已经建立了文件访问路径(即系统调用中的文件描述符)

在标准的输入输出库中,对应的文件描述符被称为流,它被实现为指向结构文件的指针。

启动程序时,会自动打开三个文件流。它们是:

标准输入:

Stdout:标准输出

标准误差输出

下面将介绍一些常用的输入输出库函数:

5.1 fopen功能

fopen函数类似于系统调用中的open函数。像open一样,它返回文件的标识符,但在这里它被称为stream,在库函数中它被实现为指向文件的指针。

如果需要显式控制设备的行为,最好使用底层系统调用,因为这样可以避免使用库函数带来的一些意想不到的副作用,比如输入输出缓冲。

功能原型:

# includestdio.h

FILE *fopen(const char *filename,const char *模式);

参数描述:

*文件名:打开文件的文件名

*模式:打开的模式

r以只读方式打开文件,并且该文件必须存在。r以读/写方式打开文件,文件必须存在。Rb读/写打开一个二进制文件并允许读取数据。读写打开一个文本文件,允许读写。w打开一个只写文件。如果文件存在,文件长度将被清除为0,即文件内容将消失。如果文件不存在,创建文件w并打开可读可写的文件。如果文件存在,文件长度将清零,即文件内容消失。如果文件不存在,请创建该文件。

Fopen在成功时返回一个非空的FILE *指针。失败返回空值

5.2 fread/fwrite功能

fread函数从文件流中读取数据,对应于系统调用中的读取;fwrite函数从文件流中写入数据,对应于系统调用中的写入

功能原型:

# includestdio.h

size_t fread(void *ptr,size_t size,size_t nitems,FILE * stream);

参数描述:

*ptr读取数据缓冲区,即存储读取的数据。

大小:指定每个数据记录的长度。

Nitems: count,给出要传输的记录数。

返回值:成功读入数据缓冲区的记录数。当它到达文件末尾时,它的返回值可能会消耗nitems,甚至是0

size_t fwrite(const coid *ptr,size_t size,size_t nitimes,FILE * stream);

他将数据从指定的数据缓冲区ptr写入文件流,并返回成功写入的记录数。

5.3 fclose功能

fclose函数关闭指定的文件流,这将导致所有未写入的数据被写出。因为stdio库函数缓冲数据,所以调用fclose函数很重要。

如果程序需要确保所有的数据都被写出来,它应该调用fclose函数。虽然在程序正常结束时会自动调用fclose函数,但是无法检测到调用fclose导致的错误。

功能原型如下:

# includestdio,h

int fc lose(FILE * stream);

5.4 fflush功能

fflush函数写出文件流中所有未写的数据。为了效率,在使用库函数的时候会用到数据缓冲区,只有缓冲区满了才会执行写操作。使用fflush函数

无论缓冲区是否已满,您都可以写出缓冲区中的所有数据。fclose的执行隐式调用fflush函数,所以在fclose执行之前不需要调用fflush。

功能原型:

# includestdio.h

int fflush(FILE * stream);

6 /proc文件系统

Linux把一切都当作文件,硬件设备在文件系统中也有相应的条目。/dev目录中的文件使用底层系统调用的特殊方式来访问硬件。

/proc文件系统可以看作是一种特殊的文件系统。在这个系统中,每个文件对应一个独立的硬件,所以用户可以通过proc文件系统访问像文件这样的硬件设备。

文件系统通常表示为/proc目录。该目录包含许多特殊文件,允许对驱动程序和内核信息进行高级访问。

如果想知道CPU信息,内核版本信息等。可以使用proc文件系统。

/proc目录中的文件因系统而异。我的计算机上/proc中的文件如下:

在大多数情况下,可以通过直接读取这些文件来获取状态信息。

6.1访问设备信息

例如,获取中央处理器信息:

内存使用信息(仅显示本地~):

每次他们阅读这些文件的内容,他们提供的信息都会及时更新。所以再次读取meminfo文件会得到不同的结果。

特定内核函数给出的更多信息可以在proc目录的子目录中找到。

6.2检查内核函数给出的信息

例如,要查看网络套接字的使用统计信息:

6.3通过过程查看过程信息

使用ps命令获取当前正在运行的进程,每个进程在proc中都有对应的信息文件。通过查看此文件,您可以了解与流程相关的信息:

进程2754当前的工作目录是:/hme/yyl

程序/bin/su正在运行,其他信息在此不再赘述。

修改proc文件系统内容

例如,系统中所有正在运行的程序同时打开的文件总数是Linux内核的一个参数。

如果我们想增加歌曲价值,我们可以通过编写相同的文件来实现。

注意:写proc的时候要注意权限问题,修改的时候要小心。不正确的值可能会影响系统的运行。

更多资讯
游戏推荐
更多+