Assignment 12, Solutions

Part of the homework for 22C:112, Spring 2012
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Notice: This entire homework is in preparation for the final machine problem:
  1. Background: Read the man pages for shmat, shmget, mmap and clone system calls.

    a) These can be used to create a situation where a parent process and a child process share memory with each other (in some cases, you may also need to use fork or other system calls to set this up), but there are differences that are the result of the way Unix/Linux evolved. Identify the three basic alternatives, and for each, describe the most significant thing it does that is different from the others. (1 point)

    shmget() can be used to create or access a persistent shared memory segment, named by a non-textual key. If IPC_PRIVATE is specified as the shared memory key, it can be used to create a temporary unnamed shared memory segment. In either case, shmat() can then be used to map this shared segment into the address space of a process. Creation of processes to share the segment is done by other means, such as fork()

    mmap() can be used to map a memory segment to a file, or to an anonymous memory segment if the MAP_ANONYMOUS option is set. The mapped segment may optionally be shared. Creation of processes to share the segment is done by other means, such as fork()

    clone() creates a new process that shares the entire address space of the calling process. This therefore, includes a control-structure element where the previous two alternatives only served to manipulate the address space.

    b) You have two functions, call them a() and b(); you want these functions to share a read-write memory area of at least s bytes, pointed to by the pointer p. which of the 3 methods described above leads you to the simplest way to do this? Give a short argument justifying your conclusion, without actually giving code; all you need to do is explain what makes one or the other solution more difficult than the one you select. Note that you may want to start on part c first before commiting yourself to an answer. (1 point)

    Of the above, clone() is clearly the lightest-weight approach; this will be demonstrated in the answers provided to part c).

    c) Give a skeleton of the code for the solution you selected in part b. As a skeleton, this needs to say what functions to call in what order, but it need not contain all the declarations and may simplify some functions by leaving out details of some parameters, so long as you include all of the key control structures. (1 point)

    /* AN SHMGET/SHMAT SOLUTION */
    /* Note that the hard part involved all the effort of
       working through the options to shmget() and shmat(). */
    
    int shmid = shmget( IPC_PRIVATE, s, IPC_CREAT | S_IRWXU );
    char * p = shmat( shmid, NULL, 0 );
    if (fork()) { /* parent */
            a( p );
            wait();
    } else { /* child */
            b( p );
            exit();
    }
    shmdt( p );
    
    /* AN MMAP SOLUTION */
    /* Note that the hard part involved all the effort of
       working through the options to mmap(). */
    
    char * p;
    p = mmap( NULL, s, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANONYMOUS 0, 0 );
    
    if (fork()) { /* parent */
            a( p );
            wait();
    } else { /* child */
            b( p );
            exit();
    }
    munmap( p, s );
    
    /* A CLONE SOLUTION */
    /* Note that the hard part involved allocating the child's stack.
       Also note that this code may not be portable because stacks
       might grow the other way on some systems. */
    
    char * p[s]; /* the required shared memory */
    
    ptr_type * newstack = malloc( STACKSIZE * sizeof(ptr_type) );
    clone( b, &(newstack[ STACKSIZE-1 ]), SIGCHLD, p );
    a( p );
    wait(); /* wait for child process termination signal */