CS-350 - Fundamentals of Computing SystemsHomework Assignment #2 - BUILDDue on September 28, 2023 — Late deadline: September 30, 2023
CBUILD Problem 1
In this BUILD problem, you are tasked with improving the design of your server to allow it to perform itsown queue management. This includes taking measurements of the length of the queue of pending packets,and also (in future assignments) to reorder the items in the queue of pending requests.Output File: server_mt.cIn this BUILD problem, you will first improve the design of your server to be able to become multi-threaded.The advantage of a multi-threaded server design is that you will be able to separate the receipt ofnewrequests from their handling.In a nutshell, with the server design you used in BUILD assignment #1, once the server is awaiting a packetwith a recv(...) operation, there is nothing else that the server can do.Indeed, the server is blocked waitingfor new requests. And it also means that during the busywait loop that corresponds to theprocessing of arequest, the server is unable to promptly receive new packets.In order to solve both problems, design a (simple) multithreadedimplementation of your server!The design will be as follows. First recall the general structure of your current singlethreaded server. Theprocess performs the following series of initialization operations: (1) a socket(...) call; (2) a bind(...)call; (3) a listen(...) call; an (4) accept(...) call. Ifthe accept(...) call is successful, we know thata connection with a client has been established successfully.After that, the server runs the handle_connection(...) function that is basically a loop of recv(...)calls. Whenever a recv(...) returns, we have a valid packet (or an error that terminates the connect). Wewill now redesign the behavior of the handle_connection(...) function.The new logic will be as follows. Right before starting the recv(...) loop (just do not dothat inside theloop!), we will start a new thread that will be dedicated to processing requests. This is typically called a“worker” thread. We will refer to the original process that creates the thread as the parent process, and tothe worker thread as the child process1
In order to create and start the worker thread in the parent process, use the clone(...) system call asdescribed in class. (1) The first parameter will have to be the name of a function, say worker_main (i.e.,a function pointer) written by you that return an int and takes a void as the only parameter. Thisfunction will serve as the “main” function of the child thread. (2) The second parameter to the clone(...)will be a piece of memory that the child will use as its stack memory. You can pass any piece of memoryyou allocate for the purpose. Just make sure it is larger than 4 KB. (3) Set the thirdparameter (flags)to (CLONE_THREAD | CLONE_VM | CLONE_SIGHAND) (see man pages to understand why). (4) Finally, passas the fourth argument any pointer that you want to pass to the workerthread,casted to (void ). Whatyou pass here will be passed to the worker thread via the parameter of the worker_main function.For this part, simply define the behavior of the worker_main as follow. Upon spawning, theworker threadwill output the string:[#WORKER#] <timestamp> Worker Thread Alive!Where <timestamp> is the current time taken using clock_gettime(...) in seconds with enough decimalpoints to capture microseconds.Next, it will enter a forever loop that only does three things in each iteration: (1) busywait for exactly 1second; (2) print out the following message:[#WORKER#] <timestamp> Still Alive!and finally (3) sleep for exactly 1 second. Then rinse and repeat. That’s it!Other than the creation of the worker thread, the parent will still perform all the operation that it wasperforming in hw1, that is get requests and busywait for the requested lenght, and output a full report ofthe incoming requests, their timestamps and length. Again, with the same exact format as before.1Funnily enough, this is actually the official terminology used to refer to the relationshipbetween processes/threads!
BUILD Problem 2
BUILD Problem 2Output File: server_q.cIn this part, we will now delegate request handling to the worker thread instead of the parent thread. Thegoal is to have the following structure.The parent process will only perform recv(...) calls, while the worker thread will NOT do any useless1-second sleep or busywait like in Part , and also get rid of any print where the worker declares to be alive.Instead, the worker thread will process the requests sent by the client by busywait’ing for the requestedamount of time. Because requests are recv’d in the parent, any packet correctly recv’d by the parent willbe put in a queue located in memory. The child worker thread will then pop/remove requests from thequeue and handle them by performing a busywait of the appropriate length just like in hw1. You are free touse your own favorite data structure to implement the shared request queue.Because regardless of how you implement the queue, it will be shared between parent and child, we need toprotect the queue against corruption happening due to unrestricted simultaneous activity of parent and childprocesses. You will learn all about how to do this a bit later into the semester, so, for now, two template functions to handle queue addition and removal are provided: (1) int add_to_queue(struct request, ...)and (2) struct requestget_from_queue(...). Because these are just templatefunctions, youwill haveto implement their internals. But make sure tofollow the comments I left for you in the code to know whichparts NOT to touch.
The function int add_to_queue(struct request, ...) should be used in the parent. It takes a requestand some other parameters of your choice to add a request to theshared queue. The suggested semantics ofthe return value is to return 0 in case of successful insert, and -1 in case of error (e.g., if the queue is full).The function struct request get_from_queue(...) should be used in the child to retrieve the next element from the queue. You might want to return NULL if thequeue is empty, but that should never happenbecause the provided code in the template of the two functions makes sure that the childis blocked if thereis nothing in the queue.Apart from processing the requests, the worker thread will print outtwo pieces of information.
1. Like before, whenever the worker thread completes processing of a request, it will have to print the reportin the format below, which is similar to but a bit different than what you printed in hw1. Thisis printed onits own line.
R<request ID>:<sent timestamp>,<request length>,<receipt timestamp>,<start timestamp>,<completion timestamp>
Here, <request ID> is the ID of the request as sent by the client; <sent timestamp> is the timestamp at
which the request was sent by the client; <request length> is the length of the request as sent by the client;
<receipt timestamp> is the timestamp at which the parent process received the request; <start timestamp>
is the timestamp at which the worker thread de-queued the request and started processing it; and
<completion timestamp> is the timestamp at which the worker thread completed processing of the request
and sent a response back to the client. All the timestamps should be expressed in seconds with decimal
digits with enough precision to capture microseconds.
2. Right after starting to process of a given request, but before picking up the next request to process (ifany) from the queue, the client must print out the current status of the queue, on its own line, according tothe following format:Q:[R<request ID>,R<request ID>,...]Problem 2 continued on next page. . CS-350 - Fundamentals of Computing Systems::Homework Assignment #2 - BUILD Problem 2 (continued) Here, <request ID> is the ID of the request as sent by the client and queued for later processing. So for instance, say that we receive only two requests, both of length 10 and at times 0 and 1, respectively. The full output will look something like this (assuming no overheads):
BUILD Problem 3
Submission Instructions: in order to submit the code produced as part of the solution for this homeworkassignment, please follow the instructions below.You should submit your solution in the form of C source code. To submit your code, place all the .cand .h files inside a compressed folder named hw2.zip. Make sure they compile and run correctly according to the provided instructions. The first round of grading will be done by running your code.Use CodeBuddy to submit the entire hw2.zip archive at https://cs-people.bu.edu/rmancuso/courses/
cs350-fa23/codebuddy.php?hw=hw2. You can submit your homework multiple times until the deadline.Only your most recently updated version will be graded. You will be given instructions on Piazza on howto interpret the feedback on the correctness of your code before WX:codehelp
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。