Search code examples
perlmmapioctl

OS Page aligned allocation in Perl


A driver exposes its API by ioctl interface.

The argument for the ioctl call is a memory buffer that its address must aligned to OS page size.

For example the allocation in C would call valloc (or posix_memalign)

Simple Perl allocation of the buffer like this:

 $buffer = "\0" x  BUFFER_SIZE ;

is not enough since most probably the starting address of the scalar wont be aligned to OS page size.

Is there a simple way to achieve this?

Note: I convert the buffer to the C address like this:

 my $c_address = unpack('Q', pack('P', $buffer));

Thanks! Eyal


Solution

  • There are multiple solutions, but going by the book, you can use the IO::AIO module, which has a IO::AIO::mmap function. Basically, you'd do something like this (untested):

        use IO::AIO
    
        IO::AIO::mmap
              my $buffer, BUFFER_SIZE, IO::AIO::PROT_READ | IO::AIO::PROT_WRITE,
              IO::AIO::MAP_PRIVATE | IO::AIO::MAP_ANONYMOUS, undef
           or die "mmap failure: $!";
    

    The $buffer will be unmapped automatically when you undef it or it goes out of scope, or you can use IO::AIO::munmap $buffer.

    You can also doing it yourself in other ways by aligning some larger memory allocation, but you at least would need to query the page size, so a pure-perl solution cannot be done portably without the help of modules, and/or wasting memory.