// smtest2.c // // Dr. Glyn Gowing // LeTourneau University // COSC 4653 - Advanced Networks // // This program demonstrates how to use a lock with fork()ed processes by using // shared memory. #include // needed for printf #include // needed for mmap #include // needed for fork #include // needed for the mutex and the mutexattr structs and functions // this create_shared_memory function was found on stack exchange. void* create_shared_memory(size_t size) { // Our memory buffer will be readable and writable: int protection = PROT_READ | PROT_WRITE; // The buffer will be shared (meaning other processes can access it), but // anonymous (meaning third-party processes cannot obtain an address for it), // so only this process and its children will be able to use it: int visibility = MAP_ANONYMOUS | MAP_SHARED; // The remaining parameters to `mmap()` are not important for this use case, // but the manpage for `mmap` explains their purpose. return mmap(NULL, size, protection, visibility, 0, 0); } // end borrowed code int main() { // create mutex and mutexattr structs so we can create the mutex // these are created as shared memory so they can be accessed by both processes pthread_mutex_t *lock = (pthread_mutex_t *)create_shared_memory(sizeof(pthread_mutex_t)); pthread_mutexattr_t *attr = (pthread_mutexattr_t *)create_shared_memory(sizeof(pthread_mutexattr_t)); // initialize the mutexattr struct pthread_mutexattr_init(attr); // set it so it can be shared between processes // without this, the child will not be able to acquire the lock even if it is // in shared memory. pthread_mutexattr_setpshared(attr, PTHREAD_PROCESS_SHARED); // initialize the mutex itself, using the attributes we just created pthread_mutex_init(lock, attr); // fork() int pid = fork(); if (pid == 0) // child { printf("Child sleeping 5\n"); // sleep 5 seconds to give parent a chance to acquire lock sleep(5); // try to acquire lock. This will block until lock is acquired pthread_mutex_lock(lock); printf("child: acquired lock - Sleeping 3 seconds\n"); sleep(3); // release lock after acquiring it pthread_mutex_unlock(lock); printf("child: unlocked.\n"); } else // parent { // acquire lock immediately to force child to block pthread_mutex_lock(lock); printf("parent: acquired lock - Sleeping 10 seconds\n"); sleep(10); // release lock to give child a chance pthread_mutex_unlock(lock); printf("parent: unlocked. Sleeping 5 to let child catch up.\n"); sleep(5); } // mmap'ed memory is automatically unmapped when the process ends. return 0; }