Nginx源码分析--数据对齐posix_memalign和memalign函数

本文介绍了Nginx中内存对齐的重要性,讲解了posix_memalign和memalign函数的工作原理及区别。在Linux中,两者分配的内存可通过free释放,但在某些Unix系统中需要注意内存释放的兼容性问题。文章还探讨了数据对齐的规则,以及Linux如何通过malloc和映射实现内存分配,并提到了mallopt函数用于调整内存分配参数。
摘要由CSDN通过智能技术生成

posix_memalign函数()

/*
 * 背景:
 *      1)POSIX 1003.1d
 *      2)POSIX 标明了通过malloc( ), calloc( ), 和 realloc( ) 返回的地址对于
 *      任何的C类型来说都是对齐的
 * 功能:由posix_memalign分配的内存空间,需要由free释放。
 * 参数:
 *      p           分配好的内存空间的首地址
 *      alignment   对齐边界,Linux中,32位系统是8字节,64位系统是16字节
 *      size        指定分配size字节大小的内存
 *
 * 要求:
 *      1)要求alignment是2的幂,并且是p指针大小的倍数
 *      2)要求size是alignment的倍数
 * 返回:
 *      0       成功
 *      EINVAL  参数不满足要求
 *      ENOMEM  内存分配失败
 * 注意:
 *      1)该函数不影响errno,只能通过返回值判断
 *
 */

memalign()函数与 posix_memalign 的不同是其将分配好的内存块首地址做为返回值

 

封装 posix_memalign,如果是 Solaris 则封装 memalign

#if (NGX_HAVE_POSIX_MEMALIGN)

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;
    int    err;

    err = posix_memalign(&p, alignment, size);

    if (err) {
        ngx_log_error(NGX_LOG_EMERG, log, err,
                      "posix_memalign(%uz, %uz) failed", alignment, size);
        p = NULL;
    }

    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "posix_memalign: %p:%uz @%uz", p, size, alignment);

    return p;
}

#elif (NGX_HAVE_MEMALIGN)

void *
ngx_memalign(size_t alignment, size_t size, ngx_log_t *log)
{
    void  *p;

    p = memalign(alignment, size);
    if (p == NULL) {
        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
                      "memalign(%uz, %uz) failed", alignment, size);
    }

    ngx_log_debug3(NGX_LOG_DEBUG_ALLOC, log, 0,
                   "memalign: %p:%uz @%uz", p, size, alignment);

    return p;
}

#endif


 参考:Nginx源码完全注释(1)ngx_alloc.h / ngx_alloc.c

 

=========================

 

对齐

数 据的对齐(alignment)是指数据的地址和由硬件条件决定的内存块大小之间的关系。一个变量的地址是它大小的倍数的时候,这就叫做自然对齐 (naturally aligned)。例如,对于一个32bit的变量,如果它的地址是4的倍数,--  就是说,如果地址的低两位是0,那么这就是自然对齐了。所以,如果一个类型的大小是2n个字节,那么它的地址中,至少低n位是0。对齐的规则是由硬件引起 的。一些体系的计算机在数据对齐这方面有着很严格的要求。在一些系统上,一个不对齐的数据的载入可能会引起进程的陷入。在另外一些系统,对不对齐的数据的 访问是安全的,但却会引起性能的下降。在编写可移植的代码的时候,对齐的问题是必须避免的,所有的类型都该自然对齐。

 

预对齐内存的分配
在大多数情况下,编译器和C库透明地帮你处理对齐问题。 POSIX  标明了通过malloc( ), calloc( ), 和 realloc( )  返回的地址对于任何的C类型来说都是对齐的。在Linux中,这些函数返回的地址在32位系统是以8字节为边界对齐,在64位系统是以16字节为边界对齐 的。有时候,对于更大的边界,例如页面,程序员需要动态的对齐。虽然动机是多种多样的,但最常见的是直接块I/O的缓存的对齐或者其它的软件对硬件的交 互,因此, POSIX 1003.1d提供一个叫做 posix_ memalign( )的函数:

/* one or the other -- either suffices */
#define _XOPEN_SOURCE 600
#define _GNU_SOURCE
#include <stdlib.h>
int posix_ memalign (void **memptr,
                    size_t alignment,
                    size_t size);

* See http://perens.com/FreeSoftware/ElectricFence/ and http://valgrind.org, respectively.

调用 posix_ memalign( )成功时会返回size字节的动态内存,并且这块内存的地址是alignment的倍数。参数alignment必须是2的幂,还是void指针的大小的倍数。返回的内存块的地址放在了memptr里面,函数返回值是0.

调用失败时,没有内存会被分配,memptr的值没有被定义,返回如下错误码之一:

EINVAL

参数不是2的幂,或者不是void指针的倍数。

ENOMEM

没有足够的内存去满足函数的请求。

要注意的是,对于这个函数,errno不会被设置,只能通过返回值得到。

posix_ memalign( )获得的内存通过free( )释放。用法很简单:

char *buf;
int ret;
/* allocate 1 KB along a 256-byte boundary */
ret = posix_ memalign (&buf, 256, 1024);
if (ret) {
    fprintf (stderr, " posix_ memalign: %s\n",
             strerror (ret));
    return -1;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值