程序代写 ICT374: Unix Process Programming

ICT374: Unix Process Programming
Unix Process Programming
Objectives
• Understandtheconceptofprocess;

Copyright By PowCoder代写 加微信 powcoder

• Understandwhatconstitutesthememoryimageofa
• Understandvariousattributesofaprocess;
• Understandtheparent/childrelationshipbetween
processes;
• Beabletocreatemultipleprocesses;
• Beabletoexecuteanewprograminaprocess;
• Beabletosynchronisemultipleprocesseswithwait,
waitpid and exit system calls;
• Understandhowaprocessisterminatedandclaimed by its parent process;
• Beabletoobtaintheterminationstatusofachild process;
• Understandandbeabletoobtainandchangea process’s environment;
• Understandtheconceptofprocessgroup,sessionand control terminal, and be able to use the relevant system calls;
• Understandandbeabletocreatedaemonprocesses. Readings
• Stevens&Rago:Ch7.1-7.9,Ch8,andCh13
• Manual pages for fork, execve, waitpid, exit etc
Page 1 of 28

ICT374: Unix Process Programming
1. Process
(a) Aprocessistheexecutionofaprogram.Inorderto execute a program, the operating system must create a process to house a data structure in the memory. In addition to the PCB (Process Control Block), this data structure also includes the memory space for keeping the program instructions (text), the global data, the heap, the stack, and the process environment. We will refer to this data structure as the memory image of the process.
The following diagram depicts part of a process’ memory image that is kept in the user space, which is accessible by the programmer.
environment
data region
text region
High address
Command line arguments and environment variables
Local variables and return addresses
Dynamically allocated memories
Un-initialised global variables
Constants and initialized global variables
Program instructions
Low address
Page 2 of 28

ICT374: Unix Process Programming
(b) Manyprocessesmayexecuteconcurrently. Several processes may come from the same program. On a single processor system, all processes time-share the same CPU.
(c) Inadditiontoitsprograminstructions,aprocessis also defined by such things as:
• valuesoftheglobalvariables
• contentsoftheheap
• contentsofitsstackandenvironment • valuesoftheCPUregisters
• theprocessstateinthePCB
• I/Ostatus(alsokeptinPCB)
• openfiles(inseparatedatastructures)
Unlike the program instructions, the above data keep changing during the lifetime of the process.
(d) Aprocesshasitsownaddressspace–itdoesnot share its address space with another process. However, two processes may communicate with each other through a variety of IPCs (Interprocess Communication Mechanisms), e.g., pipes, FIFOS, files, sockets, shared memories, and message queues.
Page 3 of 28

ICT374: Unix Process Programming
(e) Aprocess(theparentprocess)cancreateanew process (its child process). Each process is identified by a unique number known as the process ID (PID).
bash (20) bash (25)
ls (28) p1 (29)
(f) Four basic system calls for process control:
3) wait: waitpid:
creates a child process by duplicating itself
loads a program into the process memory space (to replace the existing program) and start the execution of the loaded program waits for a child process to terminate and obtains the termination status of the child process
terminates the process with an exit status.
Page 4 of 28

ICT374: Unix Process Programming
2. The fork call
#include
pid_t pid;
pid = fork();
(a) fork creates a new process by duplicating itself. before fork:
after fork:
Immediately after the fork call, the contents of the text, data, heap, stack and environment in the new
Page 5 of 28

ICT374: Unix Process Programming
process are exactly same as those of the parent process, except the return value from the fork call.
(b) = -1 = 0 > 0
there is an error
the process is the child process
the process is the parent process. The return value is the PID of the child process
(c) Aftertheforkcall,boththeparentandthechild processes execute concurrently. In a single
processor system, they time-share the same processor. However, the execution order of the two processes depends on the process scheduler in the Unix kernel. To the end users, it is unpredictable!
printf (“fork …\n”);
pid = fork();
printf(“pid = %d\n”, pid);
before forking after forking
printf (“fork …\n”);
pid = fork();
printf(“pid = %d\n”, pid);
printf (“fork …\n”);
pid = fork();
printf(“pid = %d\n”, pid);
Process B (pid = 300)
Process A (pid = 200)
Process A (pid = 200)
Page 6 of 28

ICT374: Unix Process Programming
Example: by examining the return value from the fork call, you can determine whether the current process is the original parent process or the newly created child process.
/* spawn.c — demonstrate fork */
#include
#include
int main() {
pid_t pid;
printf(“Just one process so far, call fork…\n”); pid = fork();
if (pid==0)
printf(“I am the child process\n”);
else if (pid > 0)
printf(“I am parent process, child PID =
%d\n”, pid);
printf(“fork returned error code. No child\n”);
exit(0); }
Page 7 of 28

ICT374: Unix Process Programming
3. The exec family of function calls
The exec is a family of function calls used by a process to load and execute a new program in the
existing process. When a process calls one of these exec functions, the process’ existing text (i.e., the program instructions) and data (the global data, the stack and the heap) are completely replaced by those of the new program. The execution of the new program starts at the main function of the new program.
Note, however, most other properties of the process will remain unchanged (e.g., PID, and sometimes, the process environment), because no new process is created.
#include
int execl(char *pathname, char *arg0, …, (char *)0);
int execv(char *pathname, char *argv[]);
int execlp(char *filename, char *arg0, …, (char *)0);
int execvp(char *filename, char *arg[];
int execle(char *pathname, char *arg0, …, (char*)0,
char *envp[]);
int execve(char *pathname, char *arg[], char *envp[]);
These six function calls differ in:
where to locate the program file
• execl and execv use the given pathname to locate the program file
• execlp and execvp search the directories listed in the current PATH environment variable to locate the program file.
Page 8 of 28

ICT374: Unix Process Programming
in the above example, execl (…) can be replaced by the following:
execlp (“ls”, “ls”, “-lt”, (char *)0);
How are the parameters provided?
• withexecl,execlpandexecle,theparameters are provided as a list of individual strings
• withexecv,execvpandexecve,theparameters are provided as an array of strings
char * argv[] = {“ls”, “-lt”, (char *)0};
execv (“/bin/ls”, argv);
execvp(“ls”, argv);
Whether to retain the old environment in the process?
A process inherits its environment from its parent process. Noneoftheexeccalls,exceptexecle and execve, changes the existing environment of the current process.
• execle and execve use the PATH environment variable given in the parameter envp to locate the program file.
/* Example: execute program: ls -lt */ #include
int main() {
execl(“/bin/ls”, “ls”, “-lt”, (char *)0);
Page 9 of 28

ICT374: Unix Process Programming
One can replace the existing environment of the process with a new environment using either execle or execve call. To do this, you need to construct an array and store the new environment variables and their values in that array. The array is passed as the last argument to the execle or execve function.
The environment of a process is a sequence of strings such as:
PATH=/usr/bin:/bin:.
HOME=/home/staff/hong
SHELL=/bin/csh
TERM=xterm
The environment is usually set up in the shell initialization files such as .login and .cshrc (for csh shell) or .bash_profile, .bashrc and .profile (for bash shell) in a user’s home directory.
The behaviours of many Unix programs depend on some of these environment variables. One of the common methods to configure an application program is by setting up certain pre-defined environment variables in the shell.
When the shell creates a new process, these environment variables are passed to the new process from the shell process (which is the parent of the new process).
• fork: copy the environment of the parent (ie, the shell) to the child process;
• execl, execv, execlp, execvp: does not change the environment of the current process;
Page 10 of 28

ICT374: Unix Process Programming
• execle, execve: replaces the environment of the current process with the environment stored in parameter envp of the exec call.
A successful exec call will load the new program into the calling process’s memory space and completely replace the original program (as well as global data, the stack and the heap). Hence the exec function call will not return unless the call fails. When an exec call fails, it returns –1.
int main() {
printf(“executing ls -l\n”);
execl(“/bin/ls”, “ls”, “-lt”, (char *)0);
/* if the following statement is executed,
then the execl call must have failed */
printf(“execl failed to run ls -l\n”);
exit(1); }
Page 11 of 28

ICT374: Unix Process Programming
4. Theexitfunction
This function is defined in ANSI C. On a Unix system, it calls the system call _exit, which is defined in POSIX.1, to:
(1) perform clean-up operations (such as closing all open file descriptors, and release memory used by the calling process).
(2) terminate the calling process and notify its parent process with an exit status.
Note: the difference between return and exit:
(1) in the main function, both can be used to terminate
current process.
(2) in other functions, return will cause control flow to return to the calling function. While exit will terminate calling process.
#include
void exit(int exitstatus);
Page 12 of 28

ICT374: Unix Process Programming
5. wait and waitpid
The system calls wait and waitpid are used by the
calling process to synchronise with its child processes wait:
#include
#include
pid_t wait(int *statloc);
Return: child process id if OK
or -1 on error
(1) the calling process blocks until one of its child processes terminates. When the child process terminates, wait returns its pid and passes back the termination status of the child process.
termination status:
(2) The termination status is stored in address given by the parameter statloc. It is a 32-bit integer divided into two parts. The higher 16 bits contain the termination signal number if the child process was killed by a signal. Otherwise, the lower 16 bits contain the exit status if the child process was terminated by calling the exit function.
If we are not interested in the termination status of the child process, we may pass NULL pointer
((int *)0)
to the wait function.
termination signal
exit status
Page 13 of 28

ICT374: Unix Process Programming
(3) If the calling process has no child process or if each one of its child processes has already been claimed by a previous wait call, the current wait call will return immediately with return value -1.
(4) If the calling process has a child process that had already exited but not yet claimed by the wait call (such process is called a “zombie” process), the current wait call will return immediately with the pid of the zombie process and its termination status.
(5) If the parent process is terminated before its child process, the child process will be “adopted” by the init process.
When the child process terminates eventually, it will be claimed by the init process.
#include
#include
pid_t waitpid(pid_t pid, int *statloc, int option); Return: child process id if OK
or -1 on error
With the wait call, it is not possible to wait for a specific child process. This was one of the reasons why waitpid call was added later. With the waitpid call, one can wait for a specific child process. Another difference between wait and waitpid is that wait will always block if no child process is dead and at least
Page 14 of 28

ICT374: Unix Process Programming
one child process is still running. With waitpid, one may choose non-blocking wait by using the appropriate option:
pid==-1: wait for any child process
pid>0: wait for the child whose process id is pid
pid==0: wait for any child whose process group id equals to the group id of the calling process
pid<-1: wait for any child whose process group id equals to |pid|. options==0 blocking options==WNOHANG non blocking Macros for Obtaining Termination Status Since the termination status from the wait or waitpid function consists of two parts – the termination signal (if it is killed by a signal – we will discuss signals in Topic 6) or the exit status (if the process terminates voluntarily by calling the exit function), it is necessary to break the two parts in order to obtain the exit status or the termination signal. Unix systems have defined a number C Macros for this purpose. For example, to see if the process was terminated by calling the exit function, we use WIFEXITED(termination_status) If the above macro returns true, the process was terminated voluntarily. Similarly to see if the process was terminated by a signal, use WIFSIGNALED(termination_status) Page 15 of 28 ICT374: Unix Process Programming If the process terminates voluntarily, we can find out the exit status of the process: WEXITSTATUS(termination_status) If the process was killed by a signal, we can find out the signal number used to kill the process: WTERMSIG(termination_status) For full details of these macros, you should consult the manual pages for wait and waitpid functions. For example, use command: man -S 2 wait Page 16 of 28 ICT374: Unix Process Programming 6. Process Synchronization A parent process and its child process can synchronise with each other with the wait (and waitpid) and exit calls, as shown in the following example: /* runls -- run “ls” in a child process */ #include
#include
#include
#include
int main() {
pid_t pid = fork();
/* if parent, wait until child finishes */
if (pid > 0)
wait ( (int *)0);
printf(“ls completed\n”);
/* if child, exec ls */ if (pid == 0)
execl (“/bin/ls”, “ls”, “-l”, (char *)0);
perror(“execl failed”);
/* pid < 0, fork failed */ perror("fork failed"); exit(1); } Page 17 of 28 ICT374: Unix Process Programming 7. Process Environment Environment Variables on the command line, command env will display a list of environment variables (and their values) PATH = /bin:/usr/bin: /usr/ucb: /lsdsn/bin: USER = hong SHELL = /bin/csh TERM = vt100 An environment variable can be created, set or changed by setenv command (under csh shell), or using export command (under bash shell). The environment of a process is inherited from its parent process during fork and exec (execl, execv, execlp, execvp) calls. (b) Accessing Environment int main (int argc, char *argv[], char *envp[]) int i = 0; while (envp[i] != NULL) printf(“%s\n”, envp[i] ); Page 18 of 28 ICT374: Unix Process Programming Page 19 of 28 ICT374: Unix Process Programming Obtain an environment variable char *name, *value; value = getenv(name); if ((s=getenv("USER")) != NULL ) printf("The user is %s\n", s); Method 2: (POSIX.1 compliant) extern char **environ; int main() { while (environ[i] != NULL ) printf(“%s\n”, environ[i]); Page 20 of 28 ICT374: Unix Process Programming 8. Process Groups and Sessions Apart from parent-child relationship, processes are also organized into sessions and process groups. Each process belongs to one process group, and each process group belongs to one session. A session is a collection of process groups, usually associated with the same control terminal. The process groups that are created under a terminal login session (either terminal login using RS232 or network terminal login using TELNET or SSH protocol) are placed in the same session, unless some of those processes choose to create new sessions. A process group is a collection of processes. Usually a process inherits its process group from its parent process (hence also its session), unless it chooses to create a new process group, or it is placed in a different process group by its parent process. On shells that support job control, all processes in the same job are placed in the same process group. %ls–lt |grepjohn|more processes ls, grep and more are placed in the same process group under bash shell (or other shells that support job control). For example, assuming that there are currently two login sessions on a computer, one from the local terminal (ttya) and the other from remote computer via ssh (ttyb). Page 21 of 28 ICT374: Unix Process Programming On terminal ttya ttya% a.out & ttya% ls -lt | grep john | more On terminal ttyb: ttyb% bigstuff | grep xyz > foo &
ttyb% myproc &
ttyb% cat readme | grep apple
We would see two sessions:
Page 22 of 28

ICT374: Unix Process Programming
9. Process Group
Each process group is identified by a unique process group ID. A process group may have a group leader. The leader’s process group ID equals to its own process ID.
A process can join an existing process group or create a new process group by calling setpgid:
#include
#include
int setpgid(pid_t pid, pid_t pgid);
Returns 0 if OK
or -1 on error
This call places the process with process ID = pid into the process group with group ID = pgid. Here a process can only put itself (with pid=0) or one of its children (with pid>0) into another process group. If pgid=0, then pid is used as the process group ID.
Example: the function call setpgid(0,0);
would create a new process group whose group ID equals to the pid of the calling process. The calling process becomes the group leader of the new process group.
Page 23 of 28

ICT374: Unix Process Programming
10. Daemon Process
In the Unix system, a daemon process is one that usually does not have a controlling terminal and continues to run unless it is explicitly terminated. A daemon process is often used to run a server program such as web server and SSH server.
To turn a normal process into a daemon, the following issues need to be considered:
(a) Not to be terminated at logout.
The process is not terminated when the session in which the process was created is closed. Assume that you logged in and then started a process in the background. When you logged out, the parent process, usually the shell, would terminate all its child processes, including that background process, automatically. Therefore, we need to make sure that when you log out, the daemon process will not be terminated automatically by its parent.
(b) Not to have a controlling terminal.
A normal process has a control terminal. Its behaviour can be affected by the terminal activities such as certain keystrokes. For example, typing CTRL-C or CTRL-\ will usually terminate all foreground processes. In order to prevent keyboard activities from interfering with the daemon process, the daemon should be moved out of the session in which it was created and moved to a session that has no controlling terminal. In this way, the keyboard activities will have no effects on the daemon processes.
Page 24 of 28

ICT374: Unix Process Programming
(c) Setting up appropriate current directory.
When a process is created it remembers the current directory of the shell (or parent process) immediately befo

程序代写 CS代考 加微信: powcoder QQ: 1823890830 Email: powcoder@163.com