Chapter 13 - Systems Programming

Quiz

1. How can you tell when youíve reached the end of a file?
When using the read () system call, zero is returned when the end of the file has been reached.
2. What is a file descriptor?
A file descriptor is an integer value that refers to an open file.
3. Whatís the quickest way to move to the end of a file?
While the file is open, you could use the lseek () system call to move to the end of the file. If the reason youíre moving to the end is to add information to the file, you can also open it with the O_APPEND flag to the open () system call.
4. Describe the way that shells implement I/O redirection.
Most shells implement I/O redirection by using dup () (or dup2 () ) to duplicate the file descriptors opened by the parent shell. The child shell can then close the parentís file descriptors and use its own, having modified them as required by redirection or pipe symbols. This way the file descriptors belonging to the parent shell are unaffected by the child shell.
5. What is an orphaned process?
An orphaned process is a process whose parent process has terminated.
6. How is a task run in two processes different from a task run in two threads?
Tasks running in separate threads still share process space and resources (i.e. memory, open file descriptors, etc.). Tasks running in separate processes do not share anything (unless they have a parent/child relationship because of a call to fork () ).
7. Under what circumstances do zombies accumulate?
A zombie process is one that is waiting for its parent to accept its termination code. Zombie processes might accumulate if the program running in the parent process is poorly written and never calls wait () to pick up the childís termination signal.
8. How can a parent find out how its children died?
The wait () system call returns the exit code of the child process.
9. Whatís the difference between execv () and execvp ()?
The execv () system call requires an absolute pathname of the program to be execíd whereas the execvp () call will search the processís $PATH variable to find the program.
10. Why is the name of the system call kill () a misnomer?
The name of the kill command is a misnomer because what it really does is send a signal to a process. While it can be used to send any signal, it is most often used to send a SIGTERM signal which usually kills the process.
11. How can you protect critical code?
You can surround critical code with calls to the signal () system call to have the process ignore signals and then re-enable signals after the critical code section has been executed.
12. What is the purpose of process groups?
Process groups can be used to send the same signal to a group of related processes.
13. What happens when a writer tries to overflow a pipe?
If a pipe fills up, the writing process is suspended until such time as there is room in the pipe for it to continue.
14. How can you create a named pipe?
The mknod utility or mknod () system call is used to created a named pipe.
15. Describe the clientñserver paradigm.
Separate programs, known as clients and servers, cooperate by sending data back and forth across some communications mechanism (e.g. a pipe, a file, or a network) to accomplish a task. The server usually provides information or a service to one or more requesting clients.
16. Describe the stages that a client and a server go through to establish a connection.
In a clientñserver scenario, a server process runs and waits for requests from a client program for some service. The server listens on a well known port and accepts network connections from various client programs, provides the service or information, and closes the connection.

Exercises

13.1 Write a program that catches all signals sent to it and prints out which signal was sent.  Then issue a ìkill -9î command to the process. How is SIGKILL different from the other signals? [level: easy]
You should notice that a SIGKILL won't print out the message because the process is terminated immediately. All other signals, including the default SIGTERM, can be trapped so that the message can be printed.
13.2 Write a program that takes a single integer argument n from the command line and creates a binary tree of processes of depth n. When the tree is created, each process should display the phrase ìI am process xî and then terminate. The nodes of the process tree should be numbered according to a breadth-first traversal.
Make sure that the original parent process does not terminate until all of its children have died. This is so that you can terminate the parent and its children from your terminal with Control-C. [level: medium]
This program should call fork () twice to generate two child processes for each level. The child code segment will need to print the message and then check to see if it is the last level to be generated. If it is not, then it should repeat a pair of fork () processes of its own. The parent should call wait () to wait on each of its children to terminate.
13.3 Write a program that creates a ring of three processes connected by pipes. The first process should prompt the user for a string and then send it to the second process. The second process should reverse the string and send it to the third process. The third process should convert the string to uppercase and send it back to the first process. When the first process gets the processed string, it should display it to the terminal. When this is done, all three processes should terminate. [level: medium]
This program should create the pipes and then fork () two children. The parent process will then do the prompting and other I/O to the terminal and communicate with the other processes via the pipes that all share.
13.4 Rewrite the ìghoulî exercise of Chapter 5, using the C language. [level: medium]
The program will use the signal () system call to trap the signal and then exec () a copy of itself.
13.5 Write a program that uses setuid () to allow a user to access a file that he or she would not normally be able to access. [level: medium]
The lesson is in the activity.

Projects

All of the projects in this chapter are fairly involved programming projects.