OS-Chapter3-Process Management

·

12 min read

these needs resulted in the notion of a process, which is a program in execution. A process is the unit of work in a modern computing system. The status of the current activity of a process is represented by the value of the program counter and the contents of the processor’s registers In contrast, a process is an active entity, with a program counter specifying the next instruction to execute and a set of associated resources. A program becomes a process when an executable file is loaded into memory Two common techniques for loading executable files are double-clicking an icon representing the executable file and entering the name of the executable file on the command line (file://C:/Users/ccc/Documents/Gridea/post-i..) 4 or 3 status New |process is being created --|-- Running | instructions are being executed Waiting| process is wating for some event to occur Ready| process is waiting to be assigned to a processor. Terminated| process has finished execution The objective of multiprogramming is to have some process running at all times ==榨干cpu so as to maximize CPU utilization. 3.2 Including the initial parent process, how many processes are created by the program shown in Figure 3.31? 3.3 Original versions of Apple’s mobile iOS operating system provided no means of concurrent processing. Discuss three major complications that concurrent processing adds to an operating system. 3.4 Some computer systems provide multiple register sets. Describe what happens when a context switch occurs if the new context is alreadyloaded into one of the register sets. What happens if the new context is in memory rather than in a register set and all the register sets are in use? 3.5 When a process creates a new process using the fork() operation, which of the following states is shared between the parent process and the child process? a. Stack b. Heap c. Shared memory segments 3.6 Consider the “exactly once”semantic with respect to the RPC mechanism. Does the algorithm for implementing this semantic execute correctly even if the ACK message sent back to the client is lost due to a network problem? Describe the sequence of messages, and discuss whether “exactly once” is still preserved. 3.7 Assume that a distributed system is susceptible to server failure. What mechanisms would be required to guarantee the “exactly once” semantic for execution of RPCs? 3.8 Describe the actions taken by a kernel to context-switch between processes. 3.9 Construct a process tree similar to Figure 3.7. To obtain process information for the UNIX or Linux system, use the command ps -ael. Use the command man ps to get more information about the ps command. The task manager on Windows systems does not provide the parent process ID, but the process monitor tool, available from technet.microsoft.com, provides a process-tree tool. 3.10 Explain the role of the init (or systemd) process on UNIX and Linux systems in regard to process termination. 3.11 Including the initial parent process, how many processes are created by the program shown in Figure 3.32? 3.12 Explain the circumstances under which the line of code marked printf("LINE J") in Figure 3.33 will be reached. 3.13 Using the program in Figure 3.34, identify the values of pid at lines A, B, C, and D. (Assume that the actual pids of the parent and child are 2600 and 2603, respectively.) 3.14 Give an example of a situation in which ordinary pipes are more suitable than named pipes and an example of a situation in which named pipes are more suitable than ordinary pipes. 3.15 Consider the RPC mechanism. Describe the undesirable consequences that could arise from not enforcing either the “at most once” or “exactly once” semantic. Describe possible uses for a mechanism that has neither of these guarantees. 3.16 Using the program shown in Figure 3.35, explain what the output will be at lines X and Y. 3.17 What are the benefits and the disadvantages of each of the following? Consider both the system level and the programmer level. a. Synchronous and asynchronous communication b. Automatic and explicit buffering c. Send by copy and send by reference d. Fixed-sized and variable-sized messages 3.18 Using either a UNIX or a Linux system, write a C program that forks a child process that ultimately becomes a zombie process. This zombie process must remain in the system for at least 10 seconds. Process states can be obtained from the command ps -l The process states are shown below the S column; processes with a state of Z are zombies. The process identifier (pid) of the child process is listed in the PID column, and that of the parent is listed in the PPID column. Perhaps the easiest way to determine that the child process is indeed a zombie is to run the program that you have written in the background (using the &) and then run the command ps -l to determine whether the child is a zombie process. Because you do not want too many zombie processes existing in the system, you will need to remove the one that you have created. The easiest way to do that is to terminate the parent process using the kill command. For example, if the pid of the parent is 4884, you would enter kill -9 4884 3.19 Write a C program called time.c that determines the amount of time necessary to run a command from the command line. This program will be run as "./time " and will report the amount of elapsed time to run the specified command. This will involve using fork() and exec() functions, as well as the gettimeofday() function to determine the elapsed time. It will also require the use of two different IPC mechanisms. The general strategy is to fork a child process that will execute the specified command. However, before the child executes the command, it will record a timestamp of the current time (which we term “starting time”). The parent process will wait for the child process to terminate. Once the child terminates, the parent will record the current timestamp for the ending time. The difference between the starting and ending times represents the elapsed time to execute the command. The example output below reports the amount of time to run the command ls : ./time ls time.c time Elapsed time: 0.25422 As the parent and child are separate processes, they will need to arrange how the starting time will be shared between them. You will write two versions of this program, each representing a different method of IPC. P-8 Chapter 3 Processes The first version will have the child process write the starting time to a region of shared memory before it calls exec(). After the child process terminates, the parent will read the starting time from shared memory. Refer to Section 3.7.1 for details using POSIX shared memory. In that section, there are separate programs for the producer and consumer. As the solution to this problem requires only a single program, the region of shared memory can be established before the child process is forked, allowing both the parent and child processes access to the region of shared memory. The second version will use a pipe. The child will write the starting time to the pipe, and the parent will read from it following the termination of the child process. You will use the gettimeofday() function to record the current timestamp. This function is passed a pointer to a struct timeval object, which contains two members: tv sec and t usec. These represent the number of elapsed seconds and microseconds since January 1, 1970 (known as the UNIX EPOCH). The following code sample illustrates how this function can be used: struct timeval current; gettimeofday(&current,NULL); // current.tv sec represents seconds // current.tv usec represents microseconds For IPC between the child and parent processes, the contents of the shared memory pointer can be assigned the struct timeval representing the starting time. When pipes are used, a pointer to a struct timeval can be written to—and read from— the pipe. 3.20 An operating system’s pid manager is responsible for managing process identifiers. When a process is first created, it is assigned a unique pid by the pid manager. The pid is returned to the pid manager when the process completes execution, and the manager may later reassign this pid. Process identifiers are discussed more fully in Section 3.3.1. What is most important here is to recognize that process identifiers must be unique; no two active processes can have the same pid. Use the following constants to identify the range of possible pid values:

#define MIN PID 300

#define MAX PID 5000 You may use any data structure of your choice to represent the availability of process identifiers. One strategy is to adopt what Linux has done and use a bitmap in which a value of 0 at position i indicates that P-9 Programming Problems a process id of value i is available and a value of 1 indicates that the process id is currently in use. Implement the following API for obtaining and releasing a pid: • int allocate map(void)—Creates and initializes a data structure for representing pids; returns −1 if unsuccessful, 1 if successful • int allocate pid(void)—Allocates and returns a pid; returns −1 if unable to allocate a pid (all pids are in use) • void release pid(int pid)—Releases a pid This programming problem will be modified later on in Chapter 4 and in Chapter 6. 3.21 The Collatz conjecture concerns what happens when we take any positive integer n and apply the following algorithm: n = { n∕2, if n is even 3 × n + 1, if n is odd The conjecture states that when this algorithm is continually applied, all positive integers will eventually reach 1. For example, if n = 35, the sequence is 35, 106, 53, 160, 80, 40, 20, 10, 5, 16, 8, 4, 2, 1 Write a C program using the fork() system call that generates this sequence in the child process. The starting number will be provided from the command line. For example, if 8 is passed as a parameter on the command line, the child process will output 8, 4, 2, 1. Because the parent and child processes have their own copies of the data, it will be necessary for the child to output the sequence. Have the parent invoke the wait() call to wait for the child process to complete before exiting the program. Perform necessary error checking to ensure that a positive integer is passed on the command line. 3.22 In Exercise 3.21, the child process must output the sequence of numbers generated from the algorithm specified by the Collatz conjecture because the parent and child have their own copies of the data. Another approach to designing this program is to establish a shared-memory object between the parent and child processes. This technique allows the child to write the contents of the sequence to the shared-memory object. The parent can then output the sequence when the child completes. Because the memory is shared, any changes the child makes will be reflected in the parent process as well. This program will be structured using POSIX shared memory as described in Section 3.7.1. The parent process will progress through the following steps: a. Establish the shared-memory object (shm open(), ftruncate(), and mmap()). P-10 Chapter 3 Processes b. Create the child process and wait for it to terminate. c. Output the contents of shared memory. d. Remove the shared-memory object. One area of concern with cooperating processes involves synchronization issues. In this exercise, the parent and child processes must be coordinated so that the parent does not output the sequence until the child finishes execution. These two processes will be synchronized using the wait() system call: the parent process will invoke wait(), which will suspend it until the child process exits. 3.23 Section 3.8.1 describes certain port numbers as being well known— that is, they provide standard services. Port 17 is known as the quote-of-theday service. When a client connects to port 17 on a server, the server responds with a quote for that day. Modify the date server shown in Figure 3.27 so that it delivers a quote of the day rather than the current date. The quotes should be printable ASCII characters and should contain fewer than 512 characters, although multiple lines are allowed. Since these well-known ports are reserved and therefore unavailable, have your server listen to port 6017. The date client shown in Figure 3.28 can be used to read the quotes returned by your server. 3.24 Ahaiku is a three-line poem in which the first line contains five syllables, the second line contains seven syllables, and the third line contains five syllables. Write a haiku server that listens to port 5575. When a client connects to this port, the server responds with a haiku. The date client shown in Figure 3.28 can be used to read the quotes returned by your haiku server. 3.25 An echo server echoes back whatever it receives from a client. For example, if a client sends the server the string Hello there!, the server will respond with Hello there! Write an echo server using the Java networking API described in Section 3.8.1. This server will wait for a client connection using the accept() method. When a client connection is received, the server will loop, performing the following steps: • Read data from the socket into a buffer. • Write the contents of the buffer back to the client. The server will break out of the loop only when it has determined that the client has closed the connection. The date server of Figure 3.27 uses the java.io.BufferedReader class. BufferedReader extends the java.io.Reader class, which is used for reading character streams. However, the echo server cannot guarantee that it will read characters from clients; it may receive binary data as well. The class java.io.InputStream deals with data at the byte level rather than the character level. Thus, your echo server must use an object that extends java.io.InputStream. The read() method in the P-11 Programming Problems java.io.InputStream class returns −1 when the client has closed its end of the socket connection. 3.26 Design a program using ordinary pipes in which one process sends a string message to a second process, and the second process reverses the case of each character in the message and sends it back to the first process. For example, if the first process sends the message Hi There, the second process will return hI tHERE. This will require using two pipes, one for sending the original message from the first to the second process and the other for sending the modified message from the second to the first process. You can write this program using either UNIX or Windows pipes. 3.27 Design a file-copying program named filecopy.c using ordinary pipes. This program will be passed two parameters: the name of the file to be copied and the name of the destination file. The program will then create an ordinary pipe and write the contents of the file to be copied to the pipe. The child process will read this file from the pipe and write it to the destination file. For example, if we invoke the program as follows: ./filecopy input.txt copy.txt the file input.txt will be written to the pipe. The child process will read the contents of this file and write it to the destination file copy.txt. You may write this program using either UNIX or Windows pipes.