函数:void *memalign(size_t alignment, size_t size);
The obsolete function memalign() allocates size bytes and returns a pointer to the allocated memory. The memory address will be a multiple of alignment, which must be a power of two.
memalign 分配 size 字节的空间,返回指向该空间的指针,空间的地址是 alignment 的倍数,alignment 必须是 2 的乘幂。
Lunix/UNIX系统编程手册提供的示例代码中的解释如下:
/* memalign() allocates a block of memory aligned on an address that is a multiple of its first argument. By specifying this argument as 2 * 'alignment' and then adding 'alignment' to the returned pointer,we ensure that 'buf' is aligned on a non-power-of-two multiple of'alignment'. We do this to ensure that if, for example, we ask for a 256-byte aligned buffer, we don't accidentally get a buffer that is also aligned on a 512-byte boundary. */
总结
输入输出数据的缓冲由内核和stdio库完成。有时希望阻止缓冲,但这需要了解其对应用程序性能的影响。可以使用各种系统调用和库函数来控制内核和stdio换从,并执行一次性的缓冲区刷新。
进程使用posix_fadvise()函数,可就进程对特定文件可能采取的数据访问模式向内核提出建议。内核可藉此来优化对换从去告诉缓存的应用,进而提高I/O性能。
在Linux环境下,open()所特有的O_DIRECT标识,允许特定应用跳过缓冲区告诉缓存、
在对同一个文件执行I/O操作时,fileno()和fdopen()有助于系统调用和标准C语言库函数的混合使用。给定一个流,fileno()将返回相应的文件描述符,fdopen()则针对指定的打开文件描述符创建一个新的流。
图13-1是本章的重点。该图概括了stdio函数库和内核所采用的缓冲,以及对各种缓冲类型的控制机制。从图中自上而下,首先是通过stdio库将用户数据传递到stdio缓冲区,该缓冲区位于用户态内存区。当缓冲区填满时,stdio库会调用write()系统调用,将数据传递到内核高速缓冲区(位于内核态内存区)。最终内核发起磁盘操作,将数据传递到磁盘。
图13-1左侧所示为可于任何时刻显示强制刷新各类缓冲区的调用。图右侧所示为促使刷新自动化的调用:一是通过禁用stdio库的缓冲,二是在文件输出类的系统调用中启用同步,从而使每个write()调用立刻刷新到磁盘。
第13章中的示例代码如下:
/*************************************************************************\
* Copyright (C) Michael Kerrisk, 2015. *
* *
* This program is free software. You may use, modify, and redistribute it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation, either version 3 or (at your option) any *
* later version. This program is distributed without any warranty. See *
* the file COPYING.gpl-v3 for details. *
\*************************************************************************/
/* Listing 13-1 */
/* direct_read.c
Demonstrate the use of O_DIRECT to perform I/O bypassing the buffer cache
("direct I/O").
Usage: direct_read file length [offset [alignment]]
This program is Linux-specific.
*/
#define _GNU_SOURCE /* Obtain O_DIRECT definition from <fcntl.h> */
#include <fcntl.h>
#include <malloc.h>
#include "tlpi_hdr.h"
int
main(int argc, char *argv[])
{
int fd;
ssize_t numRead;
size_t length, alignment;
off_t offset;
char *buf;
if (argc < 3 || strcmp(argv[1], "--help") == 0)
usageErr("%s file length [offset [alignment]]\n", argv[0]);
length = getLong(argv[2], GN_ANY_BASE, "length");
offset = (argc > 3) ? getLong(argv[3], GN_ANY_BASE, "offset") : 0;
alignment = (argc > 4) ? getLong(argv[4], GN_ANY_BASE, "alignment") : 4096;
fd = open(argv[1], O_RDONLY | O_DIRECT);
if (fd == -1)
errExit("open");
/* memalign() allocates a block of memory aligned on an address that
is a multiple of its first argument. By specifying this argument as
2 * 'alignment' and then adding 'alignment' to the returned pointer,
we ensure that 'buf' is aligned on a non-power-of-two multiple of
'alignment'. We do this to ensure that if, for example, we ask
for a 256-byte aligned buffer, we don't accidentally get
a buffer that is also aligned on a 512-byte boundary. */
buf = memalign(alignment * 2, length + alignment);
if (buf == NULL)
errExit("memalign");
buf += alignment;
if (lseek(fd, offset, SEEK_SET) == -1)
errExit("lseek");
numRead = read(fd, buf, length);
if (numRead == -1)
errExit("read");
printf("Read %ld bytes\n", (long) numRead);
exit(EXIT_SUCCESS);
}
该程序在open文件的时候传入O_DIRECT标志,绕过缓冲区高速缓存直接I/O.
但是存在如下限制:
用于传递数据的缓冲区,其内存边界必须对齐为块大小的整数倍。
用于传输数据的缓冲区,其内存边界必须为快大小的整数倍。
待传输数据的长度必须是块大小的整数倍。
如果不遵守上述任一条,将导致EINVAL错误。块大小(block size)指设备的物理块大小,通常为512字节.
执行结果:
兄弟这本书看着怎么样,想入手一本。上下册不分开卖有点坑,都说下册翻译的巨坑。
@浪迹天涯 这本书上册翻译的还不错,下册看的人一脸懵逼,但是买的话只能一起买,比较坑。