4.1 文件概述
文件I/O在Unix下占据着非常重要的地位,曾有一句经典语句绝对可以说明file在Unix下的重要性, "In UNIX, everything is a file",APR就是本着这个思想对Unix文件I/O进行了再一次的抽象封装,以提供更为强大和友善的文件I/O接口。
APR File I/O源代码的位置在$(APR_HOME)/file_io目录下针对不同类型的操作系统,file_io下又进一步细分为四个目录:netware,os2,unix和win32。每个目录中又包含多个.c文件,每个.c文件对应一种文件操作,比如
open.c -- 封装了文件的打开、关闭、改名和删除等操作
readwrite.c -- 顾名思义,它里面包含了文件的读写操作;
pipe.c -- 包含了pipe相关操作。
还有许多这里不多说,由于文件I/O操作复杂,我们下面将仅挑出最常用的文件I/O操作进行分析。
4.2 APR文件定义
正如第一章所言,APR中为了移植方便,通常会使用自定义的常量来代替原有系统中存在的常量,并提供它们之间的相互转换,这一点对于文件也不例外。APR几乎对文件中所用到的所有的常量都进行了重新定义,包括文件权限、文件打开方式、文件类型定义等等。这部分我们集中了解APR中的这些定义。在后面的部分将很快就会使用到。
4.2.1文件类型
尽管在Unix中,一切皆文件,但是文件又分为不同类型:
1)、普通文件(regular file)。这是最常见的文件类型。UNIX中使用S_IFREG描述该类文件,而APR中使用APR_REG描述。
2)、目录文件(directory file)。这种文件包含了其他文件的名字以及指向与这些文件有关信息的指针。UNIX中使用S_IFDIR描述,在APR中使用APR_DIR描述。
3)、字符特殊文件(character special file)。这类文件通常对应系统中某些类型的设备。UNIX中使用S_IFCHR描述,而APR中使用APR_CHR描述。
4)、块特殊文件(block special file)。这类文件典型的用于磁盘设备。系统中的所有设备或者是字符特殊文件,或者是块特殊文件。UNIX中使用S_IFBLK描述,而APR中使用APR_BLK描述该类文件。
5)、FIFO文件。这类文件通常用于进程间通信,有时也称之为管道。APR中使用APR_PIPE描述该类文件。
6)、套接字描述文件。这类文件用于进程间的网络通信。UNIX中使用S_IFSOCK描述,而APR中使用APR_SOCK描述该类文件。
7)、链接文件。最后一种文件类型就是链接文件。这种文件通常仅仅指向另外一个文件。UNIX中使用S_IFLNK描述,而APR中使用APR_LNK描述该类文件。
综合上面的内容,APR定义了枚举类型apr_filetype_e来描述所有的Unix文件类型。
typedef enum {
APR_NOFILE = 0, /**< no file type determined */
APR_REG, /**< a regular file */
APR_DIR, /**< a directory */
APR_CHR, /**< a character device */
APR_BLK, /**< a block device */
APR_PIPE, /**< a FIFO / pipe */
APR_LNK, /**< a symbolic link */
APR_SOCK, /**< a [unix domain] socket */
APR_UNKFILE = 127 /**< a file of some other unknown type */
} apr_filetype_e;
为了实现APR定义和UNIX定义的转换,APR中通过函数filetype_from_mode实现从系统定义到APR定义的转换。该函数定义在filestat.c中:
static apr_filetype_e filetype_from_mode(mode_t mode)
{
apr_filetype_e type;
switch (mode & S_IFMT) {
case S_IFREG:
type = APR_REG;break;
case S_IFDIR:
type = APR_DIR;break;
……
}
}
4.2.2文件访问权限
在UNIX系统中,每一个文件都对应三组不同的访问权限,即用户存取权限、组用户存取权限和其余用户存取权限。在UNIX中,通常用S_IXXXX常量来描述这些访问权限。APR中则使用APR_FPROT_XXXX来进行替代,对应的关系如下表所示:
权限标志
|
含义
|
值
|
标准库值
|
APR_FPROT_USETID
|
允许设置用户号
|
0x8000
|
S_ISUID
|
APR_FPROT_UREAD
|
允许用户读操作
|
0x0400
|
S_IRUSR
|
APR_FPROT_UWRITE
|
允许用户写操作
|
0x0200
|
S_IWUSR
|
APR_FPROT_UEXECUTE
|
允许用户执行
|
0x0100
|
S_IXUSR
|
APR_FPROT_GSETID
|
用于设置组号
|
0x4000
|
S_ISGID
|
APR_FPROT_GREAD
|
允许组成员读取
|
0x0040
|
S_IRGRP
|
APR_FPROT_GWRITE
|
允许组成员写入
|
0x0020
|
S_IWGRP
|
APR_FPROT_GEXECUTE
|
允许组成员执行
|
0x0010
|
S_IXGRP
|
APR_FPROT_WSTICKY
|
粘贴位
|
0x2000
|
S_ISVTX
|
APR_FPROT_WREAD
|
允许其余成员读取
|
0x0004
|
S_IROTH
|
APR_FPROT_WWRITE
|
允许其余成员写入
|
0x0002
|
S_IWOTH
|
APR_FPROT_WEXECUTE
|
允许其余成员执行.
|
0x0001
|
S_IXOTH
|
APR_FPROT_OS_DEFAULT
|
操作系统的默认的属性值
|
0x0FFF
|
0666
|
在早期版本中,访问权限使用的是APR_XXXX形式,比如APR_UREAD、APR_UWRITE等等。不过目前已经作废。为了保持与低版本的兼容性,你在源文件中还能看到它们。
在APR中,文件的访问权限被定义为apr_fileperms_t类型,该类型本质上是一个32位的整数而已:
typedef apr_int32_t apr_fileperms_t;
APR中提供了两个函数用于实现从APR权限标志到UNIX系统标志位的相互转换。apr_unix_perms2mode函数用于将APR定义转换为Unix定义,apr_unix_mode2perms用于将Unix定义转换为APR定义。这两个函数都定义在fileacc.c中。从Unix转换至APR的过程无非如下:
if (mode & S_IXXXX)
perms |= APR_XXXX;
而从APR转换为Unix过程无非如下:
if (perms & APR_XXXX)
mode |= S_IXXXX;
4.2.3文件打开方式
4.2.4其余类型重定义
APR中除了对上面的常量进行了重定义之外,它还对一些类型进行了重定义,不过这些类型都仅仅是使用typedef而已,非常简单,总结归纳如下:
1)、文件属性类型apr_fileattrs_t
typedef apr_uint32_t apr_fileattrs_t;
2)、文件定位基准apr_seek_where_t
typedef int apr_seek_where_t;
3)、文件访问权限apr_fileperms_t
typedef apr_int32_t apr_fileperms_t;
4)、文件i-node结点编号apr_ino_t
typedef ino_t apr_ino_t;
5)、文件所在设备号apr_dev_t
typedef dev_t apr_dev_t;
4.3 文件描述
在Unix系统中,与文件关联的两个数据结构通常是两个:FILE和stat。前者通常称之为文件句柄,而后者则通常称之为文件的状态信息,用于描述文件的内部信息。APR中,与之对应提供了两个封装数据结构apr_file_t和apr_finfo_t,前者描述文件句柄信息,后者描述文件内部信息。
根据操作系统支持的不同,apr_file_t了可以分为四个版本,不过我们仅仅介绍Unix版本,至于Window版本,我们会提及,而其余的netware和OS/2版本我们不打算做任何分析。在Unix系统中,apr_file_t定义如下:
struct apr_file_t {
apr_pool_t *pool;
int filedes;
char *fname;
apr_int32_t flags;
int eof_hit;
int is_pipe;
apr_interval_time_t timeout;
int buffered;
enum {BLK_UNKNOWN, BLK_OFF, BLK_ON } blocking;
int ungetchar; /* Last char provided by an unget op. (-1 = no char)*/
#ifndef WAITIO_USES_POLL
/* if there is a timeout set, then this pollset is used */
apr_pollset_t *pollset;
#endif
/* Stuff for buffered mode */
char *buffer;
int bufpos; /* Read/Write position in buffer */
unsigned long dataRead; /* amount of valid data read into buffer */
int direction; /* buffer being used for 0 = read, 1 = write */
unsigned long filePtr; /* position in file of handle */
#if APR_HAS_THREADS
struct apr_thread_mutex_t *thlock;
#endif
};
该结构描述了一个文件的大部分的属性,也是整个文件I/O系统的核心数据结构之一。
filedes是文件的描述符;fname则是打开的文件的名称;is_pipe用以标记当前文件是否是管道文件;Unix中在创建匿名管道的时候会生成一个管道文件,在管道中传输的数据实际上最终都保存在匿名文件中。对于这种临时的管道文件,它的is_pipe为1;filePtr是读写文件的时候文件内部的文件指针,通常情况下这个成员只有seek函数的时候才需要使用,由于seek需要给出当前文件的内部指针位置,因此在任何的文件读和写之后,我们都必须立即调整filePtr的值,以使它指向正确的位置。direction则是记录了当前的操作类型,0是读操作,1是写操作;buffer缓冲区用以保存从文件中读取的数据,dataRead则用以记录从文件中读取到缓冲区中的有效的字节数;blocking则是记录的读取的方式,一般允许两种,即阻塞和非阻塞。对于阻塞,那么读取将等待,直到文件中有新的数据或者读取超时,超时的时间由timeout决定。
另外,如果支持多线程,那么为了保证线程访问安全性,在可能出现互斥的数据结构中都要额外的增加内部互斥锁。文件结构的内部互斥锁由变量thlock决定。任何人访问该数据结构之前都必须先获取该互斥锁,同时访问结束后该互斥锁将被释放。
关于作者
张中庆,目前主要的研究方向是嵌入式浏览器,移动中间件以及大规模服务器设计。目前正在进行Apache的源代码分析,计划出版《Apache源代码全景分析》上下册。Apache系列文章为本书的草案部分,对Apache感兴趣的朋友可以通过flydish1234 at sina.com.cn与之联系!
如果你觉得本文不错,请点击文后的“推荐本文”链接!!
分享到:
相关推荐
1. **打开配置文件**:找到Apache的配置文件,通常是`/etc/httpd/conf/httpd.conf`(Unix/Linux)或`C:\Apache24\conf\httpd.conf`(Windows)。打开文件并搜索`#IncludeOptional conf/extra/httpd-vhosts.conf`,...
当需要为Apache添加虚拟目录时,就需要在这个文件中进行相应的设置。 #### 三、如何配置Apache虚拟目录 根据题目中提供的部分内容,我们可以了解到Apache虚拟目录配置的基本步骤: 1. **打开配置文件**: - 首先...
1. **创建或编辑.htaccess文件**:如果你的Apache配置允许使用`.htaccess`文件进行局部配置,并且你希望只在某个特定目录下禁用目录浏览功能,可以在该目录下创建或编辑`.htaccess`文件。 2. **添加禁用目录浏览的...
在本文中,我们将深入探讨如何在Linux环境下安装Apache并配置中文目录支持,同时解决在添加模块和使用mod_encoding模块过程中可能遇到的问题。Apache HTTP Server是一个广泛使用的开源Web服务器,其可扩展性和灵活性...
在Ubuntu Linux系统中,Apache 2的配置文件结构较为特殊,与常见的Windows环境下的单一httpd.conf文件不同。以下是Ubuntu环境下Apache配置文件的基本架构: 1. **主配置文件**:`apache2.conf`,位于`/etc/apache2/...
本篇将详细讲解如何利用Apache进行文件上传与下载。 首先,我们需要理解Apache的HTTP协议基础,它是Web服务器和客户端之间通信的标准。当用户尝试上传或下载文件时,这些操作都是通过HTTP请求(如POST或GET)进行的...
配置虚拟目录通常在Apache的配置文件`httpd.conf`或站点特定的`.conf`文件中进行。以下是一个基本的虚拟目录配置示例: ```apacheconf *:80> ServerName example.com DocumentRoot "/var/www/example" ...
从给定的文件信息中,我们可以提取到关于Apache配置文件httpd.conf的多个关键知识点,以下是对这些知识点的详细解析: ### Apache配置文件httpd.conf的重要性 Apache的配置文件httpd.conf是Apache服务器的核心配置...
在这个场景中,我们关注的是PHP和Apache服务器的集成,以及它们如何处理默认目录、页面和文件。以下是关于这些主题的详细讨论: 首先,`PHP`是一种广泛使用的开源脚本语言,尤其适合于Web开发。它被嵌入到HTML代码...
Apache的主要配置文件是`httpd.conf`,通常位于`/etc/httpd`或`/etc/apache2`目录下。这个文件包含了服务器的所有全局设置。配置文件使用文本格式,可以通过文本编辑器进行修改。 **3. 配置指令** Apache配置文件中...
1. **定位配置文件**:首先,在终端中,使用命令`cd /etc/apache2`进入Apache的配置目录。 2. **打开配置文件**:接着,运行`vim apache2.conf`,这会启动Vim编辑器并打开`apache2.conf`。 3. **查找Directory指令**...
在本文中,我们将深入探讨如何配置Apache以监听特定端口并设置目录。首先,我们关注的是两个主要的配置文件:`httpd.conf`和`httpd-vhosts.conf`。 `httpd.conf`是Apache的基础配置文件,包含了服务器的基本设置。...
- **主配置文件**:`httpd.conf`是Apache的主要配置文件,位于安装目录下的`conf`子目录中。这个文件包含了Apache启动时需要的所有配置信息,包括监听端口、文档根目录、访问权限控制等。 - **虚拟主机配置**:通过...
- ServerRoot参数:指定服务器的安装基础目录,这个目录通常包含配置文件的子目录conf/和日志文件的子目录logs/。其他配置文件的路径都是以ServerRoot为基准。 - DocumentRoot参数:设置网络上可见的主文档树的根...
在本资源包中,你将找到用于安装Apache和配置OpenSSL的相关文件,以及用于测试其正确运行的资源。 首先,让我们深入了解一下Apache和OpenSSL: 1. **Apache HTTP Server**:Apache是开源的Web服务器,以其稳定性、...
这个文件中定义了 Apache 的各种设置,例如监听端口、文档根目录、错误日志文件等。 在 CentOS 中,还有一个特殊的配置文件/etc/httpd/conf.d/*.conf, 这个文件夹中可以包含多个小配置文件,每个文件可以单独配置 ...
1. **下载与解压** 首先,我们需要下载Apache和PHP的安装包。在这个案例中,我们已经有一个名为`php-5.2.8-Win32.rar`的PHP版本。这是一个RAR压缩文件,需使用解压工具将其解压到一个目录,例如`C:\php`。同时,...
5. WordPress与Apache文件根目录的关系 作为开发者,在学习WordPress时可能会频繁需要更改Apache的文件根目录,以便更方便地管理和访问网站文件。WordPress的安装和运行依赖于正确的服务器配置,包括合适的文件根...