Monday, May 27, 2013

Shared memory code sample 2.0

If the previous few lines of code sample didn't help, then let's try a little more.
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.