首页 理论教育Linux设备文件的打开和创建方法

Linux设备文件的打开和创建方法

【摘要】:在Linux系统中,设备文件或特殊文件是设备驱动程序的接口,出现在文件系统中就好像它是普通文件一样。表7.4文件打开方式取值

1.设备文件

从空间的角度分析,Linux系统与Windows系统之间的不同在于,Linux系统是由文件所组成的,很多东西都是以文件的形式存在的,其将设备当做文件来操作。因此,在Linux系统中,对文件的读写等操作都可以应用到设备文件中,可以把设备文件当作普通文件来处理。在访问外部设备时,不需要系统提供一个标准接口与外部设备相关联,只需要像访问普通文件一样访问设备文件。

在Linux系统中,设备文件或特殊文件是设备驱动程序的接口,出现在文件系统中就好像它是普通文件一样。这些特殊文件允许应用程序通过标准输入/输出系统调用使用其设备驱动程序与设备进行交互。使用标准系统调用简化了许多编程任务,并且无论设备的特性和功能如何,都可以实现一致的用户空间I/O机制。

设备文件通常提供与标准设备(如打印机和串行端口)的简单接口,但也可用于访问这些设备(如磁盘分区)上的特定独特资源,因此设备文件存在一个抽象化的设备目录中,如“/dev”,关于文件的读写或者控制等操作,都可以应用到设备文件上。

2.设备文件的打开和创建

基于文件描述符的文件操作函数,都是Linux操作系统提供的一组文件操作的接口函数,例如open()、close()、read()、write()、lseek()等等。要对一个文件进行操作,前提是要这个文件已经存在了,然后要打开这个文件,此时可以对这个打开的文件进行读写或者控制等操作,操作完成后,需要将文件关闭,如果不及时关闭,可能会丢失文件中的数据。因此,在Linux系统中提供了系统调用函数open()和close()用于打开和关闭一个已经存在的文件。

(1)open()函数

open()函数可以打开或创建一个文件(包括设备文件)。该函数的定义形式如下:

#include<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_tmode);

int creat(const char∗pathname,mode_tmode);

上述介绍的两个open()函数和一个creat()函数,都是调用成功时,返回其新分配的文件描述符;否则返回值为-1,并设置适当的errno值。

上述函数的定义中,参数pathname均代表要打开或者要创建的这个文件的路径名称;参数flags均代表文件的打开方式的宏定义,这些宏定义的含义如表7.2所示;而参数mode均代表文件的访问权限设置,访问权限的宏定义的含义如表7.3所示。

表7.2 open函数的flag参数定义

文件的打开方式的宏定义可以使用“|”或运算进行组合,但其中必须包括O_RDONLY、O_WRONLY或O_RDWR三种打开方式的宏定义之一。

表7.3 文件权限的宏定义

参数mode代表的文件权限,可以用八进制数表示,比如0644表示-rw-r--r--,也可以用S_IRUSR、S_IWUSR等宏定义按位或起来表示,要注意的是,文件权限由open()函数的mode参数和当前进程的umask掩码共同决定,umask掩码是系统中默认的值,可以通过在终端下输入命令“umask”查询此值。

(2)close()函数(www.chuimin.cn)

close函数主要用于关闭一个已打开的文件,该函数的定义形式如下:

#include<unistd.h>

int close(int fd);

close()函数如果调用成功,返回值为0;否则返回值为-1,并设置适当的errno值。

当一个进程终止时,内核对该进程所有尚未关闭的文件描述符调用close()函数关闭,所以即使用户程序不调用close()函数,在终止时内核也会自动关闭它打开的所有文件。但是对于网络服务器这种一直在运行的程序,文件描述符一定要及时关闭,否则随着打开的文件越来越多,会占用大量文件描述符和系统资源。

由函数open()返回的文件描述符一定是该进程尚未使用的最小描述符。由于程序启动时自动打开标准输入、标准输出和标准错误输出,因此文件描述符0、1、2会存在,那么第一次调用open()函数打开文件时,返回的文件描述符通常会是3,再调用open()函数就会返回4。可以利用这一点在标准输入、标准输出或标准错误输出上打开一个新文件,实现重定向的功能。例如,首先调用close关闭文件描述符1,然后调用open()函数打开一个常规文件,则一定会返回文件描述符1,这时候标准输出就不再是终端了,而是一个常规文件,再调用printf就不会打印到屏幕上,而是写到了这个文件中。

基于数据流的文件操作是通过一个FILE类型的文件指针实现对文件的访问,在FILE结构体类型中存储着很多关于流操作所需的信息,如打开文件的文件描述符、新开辟的缓冲区的指针、缓冲区的大小等等信息。在此并不需要了解FILE结构体中都存储着什么信息,只需使用该类型的指针与文件建立联系,用于访问文件。基于流的文件操作函数常用的有fopen()、fclose()、fread()、fwrite()、fscanf()、fgetc()等。在操作文件之前要用fopen()函数打开文件,操作结束后,要用fclose()函数关闭文件。

(3)fopen()函数

打开文件就是在操作系统中分配一些资源用于保存该文件的状态信息,用文件描述符来引用这个文件的状态信息。因此可以通过这个文件描述符对文件进行某些操作。函数fopen()的定义形式如下:

#include<stdio.h>

FILE∗fopen(const char∗path,const char∗mode);

参数path代表的是要打开的文件的路径名;参数mode指的是文件的打开方式。函数调用成功时,返回值为文件指针,否则返回NULL并设置errno信息。返回的这个文件指针主要用于以后调用其他函数对文件做读写操作,该指针用以指明对哪个文件进行操作。mode参数有如下6种取值,如表7.4所示。

表7.4 文件打开方式取值

(4)fclose()函数

fclose()函数关闭文件,即释放文件在操作系统中占用的资源,使文件描述符失效,用户程序就无法操作这个文件了。函数fclose()的定义形式如下:

#include<stdio.h>

int fclose(FILE∗fp);

参数fp是要关闭的文件的指针。函数如果调用成功,返回值为0,否则返回EOF并设置errno信息。EOF在stdio.h中定义,值为-1,它的定义形式如下:

#ifndef EOF

#define EOF(-1)

#endif