Project 3a: Multiprocess Programming with Shared Memory in LinuxYou are likely to find that it is not possible to divide this project up by "server" vs "client" (and have one person work on each part) since they need to work together closely; you are likely to have the most success if you work together. This project will not be a lot of code, but it can be tricky to use the suggested library routines correctly. You may find the discussion here useful. There are numerous objectives to this assignment:
OverviewIn this assignment, you will implement a client and server that communicate through a shared memory page to display statistics about the client processes. All of the processes are running on the same machine. Each client process will periodically write to the shared memory page with updates about its recent behavior (e.g., how much CPU it has been allocated); the server process collects this information (by reading from the shared memory page) and periodically displays the information for all the client processes. Meanwhile, each client also periodically displays the PIDs of all the processes that are currently running. As we will soon cover in the lectures, when processes (or threads) cooperate through shared memory, they require synchronization primitives (such as locks or semaphores) to ensure that they do not have race conditions when they are each simultaneously updating the same memory locations. To minimize our need for synchronization in this Project (synchronization is for Project 4!), we will construct the clients and server so that only a single client is (usually) writing to each memory location and the server is only reading (not writing); if the server happens to occasionally read data that is not up-to-date, that is okay, since the data is just usage statistics (and not your bank account). The only time you will need to worry about mutual exclusion will be when clients are first starting and when they exit. For this project, you will be implementing two components: a server process that displays client statistics every second, and a client process that sleeps and displays the PIDs of all the processes that are currently running every second. Server Process
Let us consider what the server process,
First, it is the responsibility of the server process to create and
initialize the shared memory page. A shared memory page can be
created with
This routine essentially maps the shared memory page to the tmpfs (temporary file system). After calling this routine, you will find this file at Because everyone will create the file at For example, if Zhewen works with Xiangjin for this project, then Second, you should use Third, you should use If anything goes wrong with this setup (e.g., the shared memory page cannot be exclusively created), then the After the server process creates this single page of shared memory and initializes it appropriately, it should enter an infinite loop where it continually sleeps for one second, reads the contents of shared memory, and then displays the statistics that have been written to shared memory to STDOUT. There should be one line of output for each client process; the format of each line of output should be as follows: pid : [pid], birth : [dateOfBirth], elapsed : [sec] s [msec] ms The The For example, if there are two client processes, the output may look like the following: pid : 14084, birth : Wed Jul 5 22:59:27 2017, elapsed : 30 s 4.8310 ms pid : 14085, birth : Wed Jul 5 22:59:27 2017, elapsed : 30 s 4.5600 msIf at some time, a new client starts writing to the shared memory page, the output could look like this: pid : 14084, birth : Wed Jul 5 22:59:27 2017, elapsed : 34 s 5.4670 ms pid : 14085, birth : Wed Jul 5 22:59:27 2017, elapsed : 34 s 5.1960 ms pid : 14276, birth : Wed Jul 5 23:00:02 2017, elapsed : 0 s 0.0010 msFinally, if a client (pid : 14085) terminates at some time, the output could look like this: pid : 14084, birth : Wed Jul 5 22:59:27 2017, elapsed : 91 s 14.4980 ms pid : 14276, birth : Wed Jul 5 23:00:02 2017, elapsed : 57 s 10.0560 ms
You will need to define a structure for each client's
statistics. The details of this structure are up to you. We suggest
treating the shared memory page as an array of these structures.
We've provided a definition for the type
typedef struct { int pid; char birth[25]; int elapsed_sec; double elapsed_msec; } stats_t;
You must use the fields we have defined without modifying them, but you can add to that structure. However, you cannot add too many fields such that Your server must be able to handle 63 clients. If more than 63 clients at a single time try to use this shared memory page, those clients should receive an error. When a client terminates, it must reset its segment (or some bytes of its segment depending on your implementations) in the shared memory page so that the segment can be used by another client later. One of your challenges when implementing the server will be to determine the number of valid clients; don't print out any garbage if there are fewer than 63 running clients! To ensure that only one client at a time is searching through and modifying the essential structures of the shared memory page, you should use a semaphore to provide mutual exclusion to protect the critical sections. Now let's explain why we should limit the size of the structure To use the semaphore like a simple mutex lock, you should initialize the semaphore as
The clients can then use When your server terminates, you will need to ensure that it
correctly removes the shared memory page so that your To help you start with, we have provided the code frame of shm_server.c. Client ProcessYour client process,shm_client , should behave as follows.
Multiple clients may connect simultaneously to the same server and same shared memory page.
You should first obtain the shared memory page pointer by using There is no need to initialize the semaphore (or mutex lock) in the client (because it was already initialized in the server). All you need to do here is to point the semaphore to the segment that stores the semaphore in the shared memory page. Now your client process will iterate forever. For each iteration, it first updates and writes its statistics to the particular segment of the shared memory page; then it sleeps for one second; finally it prints out the PIDs of current active clients. Below is part of the example output from one client: Active clients : 14084 14085 14276 Active clients : 14084 14085 14276 Active clients : 14084 14276
We assume that you will kill your client program by sending it a
SIGINT signal (with Ctrl-C) or a SIGTERM signal (by the command line Similarly, the server will be killed by receiving the signal. So clean the shared memory page and exit elegantly when the server terminates. To help you start with, we have provided the code frame of shm_client.c.
You should compile your code like
To ensure that we compile your server and your client process correctly, you will need to create a simple Makefile. The makefile must make both of the targets. If you don't know how to write a makefile, you might want to look at the man pages for make. To run the test scripts, go to the directory where your source codes reside and type
|