apache 文件操作函数的使用
1.apr_file_close关闭文件描述符,可以联想close()函数
apr_file_close的源代码:
APR_DECLARE(apr_status_t) apr_file_close(apr_file_t *file)
{
return apr_pool_cleanup_run(file->pool, file, apr_unix_file_cleanup);
}
实际调用apr_pool_cleanup_run
的函数
下面分析apr_pool_cleanup_run
函数原理:
APR_DECLARE(apr_status_t) apr_pool_cleanup_run(apr_pool_t *p, void *data,
apr_status_t (*cleanup_fn)(void *))
{
apr_pool_cleanup_kill(p, data, cleanup_fn);//核心的文件
return (*cleanup_fn)(data);
}
下面转到apr_pool_clean_kill()函数的使用
源代码:
/*清理函数*/
struct cleanup_t {
struct cleanup_t *next;
const void *data;
apr_status_t (*plain_cleanup_fn)(void *data);
apr_status_t (*child_cleanup_fn)(void *data);
};
清理函数结构中有一个cleanup_t
类型的结构体
apr_file_close函数实际上就是到到内存池里释放所有的资源
释放内存池资源要单独写一篇文章
文件读写
1.file_read_buffered函数使用
这是一个局部的函数
static apr_status_t file_read_buffered(apr_file_t *thefile, void *buf,
apr_size_t *nbytes)
{
apr_ssize_t rv;
char *pos = (char *)buf;
apr_uint64_t blocksize;
apr_uint64_t size = *nbytes;
if (thefile->direction == 1) {
rv = apr_file_flush_locked(thefile);
if (rv) {
return rv;
}
thefile->bufpos = 0;
thefile->direction = 0;
thefile->dataRead = 0;
}
rv = 0;
//设置读取到缓冲区的标志
if (thefile->ungetchar != -1) {
*pos = (char)thefile->ungetchar;
++pos;
--size;
thefile->ungetchar = -1;
}
//从file读取内容到buffer缓存了
while (rv == 0 && size > 0) {
if (thefile->bufpos >= thefile->dataRead) {
int bytesread = read(thefile->filedes, thefile->buffer,
thefile->bufsize);
if (bytesread == 0) {
thefile->eof_hit = TRUE;
rv = APR_EOF;
break;
}
else if (bytesread == -1) {
rv = errno;
break;
}
thefile->dataRead = bytesread;
thefile->filePtr += thefile->dataRead;
thefile->bufpos = 0;
}
blocksize = size > thefile->dataRead - thefile->bufpos ? thefile->dataRead - thefile->bufpos : size;
memcpy(pos, thefile->buffer + thefile->bufpos, blocksize);
thefile->bufpos += blocksize;
pos += blocksize;
size -= blocksize;
}
*nbytes = pos - (char *)buf;
if (*nbytes) {
rv = 0;
}
return rv;
}
2.读取文件的操作
APR_DECLARE(apr_status_t) apr_file_read(apr_file_t *thefile, void *buf, apr_size_t *nbytes)
{
apr_ssize_t rv;
apr_size_t bytes_read;
if (*nbytes <= 0) {
*nbytes = 0;
return APR_SUCCESS;
}
//如果设置了buffered标志
//就直接将file读到buffer
if (thefile->buffered) {
//加锁
file_lock(thefile);
rv = file_read_buffered(thefile, buf, nbytes);
//解锁
file_unlock(thefile);
return rv;
}
else {
bytes_read = 0;
if (thefile->ungetchar != -1) {
bytes_read = 1;
*(char *)buf = (char)thefile->ungetchar;
buf = (char *)buf + 1;
(*nbytes)--;
thefile->ungetchar = -1;
if (*nbytes == 0) {
*nbytes = bytes_read;
return APR_SUCCESS;
}
}
//实际开始读取文件
//实际调用了read函数,并不经过缓冲区的设计
//开始拷贝
do {
rv = read(thefile->filedes, buf, *nbytes);
} while (rv == -1 && errno == EINTR);
#ifdef USE_WAIT_FOR_IO
if (rv == -1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
thefile->timeout != 0) {
apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 1);
if (arv != APR_SUCCESS) {
*nbytes = bytes_read;
return arv;
}
else {
do {
rv = read(thefile->filedes, buf, *nbytes);
} while (rv == -1 && errno == EINTR);
}
}
#endif
*nbytes = bytes_read;
if (rv == 0) {
thefile->eof_hit = TRUE;//读至文件末尾
return APR_EOF;
}
if (rv > 0) {
//返回
*nbytes += rv;
return APR_SUCCESS;
}
return errno;
}
}
3,apr_file_write()函数的使用
APR_DECLARE(apr_status_t) apr_file_write(apr_file_t *thefile, const void *buf, apr_size_t *nbytes)
{
apr_size_t rv;
if (thefile->buffered) {//如果是从缓存写
char *pos = (char *)buf;
int blocksize;
int size = *nbytes;
file_lock(thefile);
if ( thefile->direction == 0 ) {
/* Position file pointer for writing at the offset we are
* logically reading from
*/
apr_int64_t offset = thefile->filePtr - thefile->dataRead + thefile->bufpos;
if (offset != thefile->filePtr)
lseek(thefile->filedes, offset, SEEK_SET);
thefile->bufpos = thefile->dataRead = 0;
thefile->direction = 1;
}
//如果设置了buffer标识,则从缓存去读写数据
rv = 0;
while (rv == 0 && size > 0) {
if (thefile->bufpos == thefile->bufsize) /* write buffer is full*/
rv = apr_file_flush_locked(thefile);
blocksize = size > thefile->bufsize - thefile->bufpos ?
thefile->bufsize - thefile->bufpos : size;
memcpy(thefile->buffer + thefile->bufpos, pos, blocksize);
thefile->bufpos += blocksize;
pos += blocksize;
size -= blocksize;
}
file_unlock(thefile);
return rv;
}
else {
//实际的读写
do {
rv = write(thefile->filedes, buf, *nbytes);
} while (rv == (apr_size_t)-1 && errno == EINTR);
#ifdef USE_WAIT_FOR_IO
if (rv == (apr_size_t)-1 &&
(errno == EAGAIN || errno == EWOULDBLOCK) &&
thefile->timeout != 0) {
apr_status_t arv = apr_wait_for_io_or_timeout(thefile, NULL, 0);
if (arv != APR_SUCCESS) {
*nbytes = 0;
return arv;
}
else {
do {
do {
rv = write(thefile->filedes, buf, *nbytes);
} while (rv == (apr_size_t)-1 && errno == EINTR);
if (rv == (apr_size_t)-1 &&
(errno == EAGAIN || errno == EWOULDBLOCK)) {
*nbytes /= 2; /* yes, we'll loop if kernel lied
* and we can't even write 1 byte
*/
}
else {
break;
}
} while (1);
}
}
#endif
if (rv == (apr_size_t)-1) {
(*nbytes) = 0;
return errno;
}
*nbytes = rv;
return APR_SUCCESS;
}
}