Of course I build on all previous premises so I won't repeat that part.
This time, playing with just 1 GiB or any other quantity is enough.
We now use ISM and manual locking to wrap up the exposition.
Some real output from the following code is here.
/*
* File: main.cpp
* Author: AZ
*
* Created on May 27, 2013, 8:46 AM
*/
#include <iostream>
#include <cerrno>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <sys/mman.h>
int main()
{
//
// Play with shared memory!
//
std::size_t const size = 1UL * 1024UL * 1024UL * 1024UL;
std::cout << "Getting shared memory: ";
int id = ::shmget( 1, size, IPC_CREAT | IPC_EXCL | 0660 );
if ( id == -1 )
{
std::cout << "Failure!" << std::endl;
}
else
{
std::cout << "Success!" << std::endl;
std::cout << "Attaching to shared memory: ";
//
// For a "standard" shared memory segment,
// don't pass any flags, that is, pass 0.
//
// SHM_RND [Optional]
// Asks to round down the address to a page boundary.
// Not necessary for ISM or DISM.
//
// SHM_SHARE_MMU
// Asks for a ISM segment locked in physical memory.
//
// SHM_PAGEABLE
// Asks for a DISM segment pageable (virtual memory).
//
void * p = ::shmat( id, 0, SHM_PAGEABLE );
if ( reinterpret_cast < intptr_t > ( p ) == -1 )
{
std::cout << "Failure!" << std::endl;
}
else
{
std::cout << "Success!" << std::endl;
std::cout << "Using shared memory..." << std::endl;
//
// Touch the whole shared segment.
// Fill it with '*'.
//
// This will force the amount reserved
// to be actually allocated (at least with DISM).
//
::memset( p, '*', size );
std::cout << "Locking shared memory: ";
if ( ::mlock( p, size ) == 0 )
{
std::cout << "Success!" << std::endl;
std::cout << "Unlocking shared memory: ";
switch ( ::munlock( p, size ) )
{
case 0:
std::cout << "Success!" << std::endl;
break;
case -1:
std::cout << "Failure!" << std::endl;
break;
default:
std::cout << "?" << std::endl;
break;
}
}
else
{
std::cout << "Failure! >>> ";
switch ( errno )
{
case EINVAL:
std::cout << "EINVAL" << std::endl;
break;
case ENOMEM:
std::cout << "ENOMEM" << std::endl;
break;
case ENOSYS:
std::cout << "ENOSYS" << std::endl;
break;
case EPERM:
std::cout << "EPERM" << std::endl;
break;
case EAGAIN:
std::cout << "EAGAIN" << std::endl;
break;
default:
std::cout << "?" << std::endl;
break;
}
}
std::cout << "Detaching shared memory: ";
switch ( ::shmdt( p ) )
{
case 0:
std::cout << "Success!" << std::endl;
break;
case -1:
std::cout << "Failure!" << std::endl;
break;
default:
std::cout << "?" << std::endl;
break;
}
}
//
// End of fun!
//
std::cout << "Removing shared memory: ";
switch ( ::shmctl( id, IPC_RMID, 0 ) )
{
case 0:
std::cout << "Success!" << std::endl;
break;
case -1:
std::cout << "Failure!" << std::endl;
break;
default:
std::cout << "?" << std::endl;
break;
}
}
return 0;
}
Also look at a small variation of the above code.