Introduction to Operating System

Lab2: Processes


Lab Overview

In this lab, you will have experiences with process creation. You'll learn how to spawn processes and execute completely different programs. First, a word of caution, when you begin with your program, it is possible that your program creates processes uncontrollably over and over, eventually causing your system to crash, for which you have to reboot your system.

It is also possible that your program may create extra processes that persist after the parent processes has finished. Use "ps" command to detect this situation, and "kill" to clean up.

Tasks:

1. ps

A process, also known as a task under Linux, is a running instance of a program. This means that if 10 users on a server are all using the same program, such as vi, then there are 10 vi processes running on the machine, although they all share the same executable code (program text).


The processes on a Linux system can be viewed using "ps" command.

On Linux, you need to type "ps -e" to see processes not attached to you current terminal. The PID column lists the process id number for a process, while TTY shows what the process is attached to (? means that is has no terminal), and last CMD is the name of the program actually running.

The process ID(PID) is a unique identifier for a process. The operating system uses a 32-bit counter last_pid to keep track of the last PID assigned to a process.

More information about the process list can be displayed using the -l option of the ps command. Notice the "S" column, which indicates the state of the process, use "man ps" to check the states of a process.

Because of the child-parent relationship among processes, you can aso view processes a tree. And the pstree command will show you all processes in the system organized as a tree. The first thing you may notice is that the tree is rooted at init. Processes whose PPID is init (i.e. 1) and that do not have a controlling terminal (and are not zombies) are called deamons. A deamon is a background server process. Usually, the executable for a deamon is suffixed with the letter 'd' to let the system administrator know that it is the server program.


Q1:Give examples of at least 3 deamons running on your computer.

2.Process Creation

In Linux, processes are created by first duplicating the parent process. This is called forking, after the fork system cal. In C, you invoke the fork system call with the fork() functions:

#include <sys/types.h>
#include <unistd.h>

pid_t fork(void);

You need both header files to use fork(). After forking, the parent and child process share the same code, and effectively have different stacks and heaps (its own seperate address space). The fork function returns a PID, which is used to identify which process it is. In the child process, fork will return 0, but in the parent fork will return PID of the newly created child (if it returns a negative value, then an error occured.) Consider the following code:

#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
	pid_t pid;
	
	pid = fork();

	if(pid == 0)
	printf("Child process!\n");
	
	else if(pid > 0)
	printf("Parent process!\n");
	
	else printf("fork failure!\n");
	exit(0);
}

Wait() and waitpid() functions can be used to make a parent process wait until a child process terminates.

Q:What the output of the following program?
#include <stdlib.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

int main(){
	pid_t pid;
	int count = 13;
	pid = fork();

	if(pid == 0){
	sleep(5);
	count = 31;
	
	}
	
	else if (pid >  0){
		wait(NULL);
	}
	
	else printf("Fork Failure!\n");	
	
	printf("There are %d apples!",count);
	exit(0);
}

3.exec

fork lets you make a copy of the current program, but what if you wanted to run a completely different program? In UNIX/LINUX, the exec system call causes a process to invoke another executable. There are many funcitons that act as front ends to the exce system call ("man exec"). These functions replace the image of the current process' with the executalbe image specified as an argument to exec. For example, the following code tries to lanch vi:

#include <stdlib>
#include <unistd.h>

int main(){
	execl("/usr/bin/vi","vi",NULL);

	/* We can only reach this code when there is an error in execl*/
	perror("execl");
	exit(1);
}

execl accepts the executalbe name as well as the command line arguments. It is a variable argument function so it many accpet multiple strings.And the argument list should be terminated with a NULL. For example if you wanted to execute the equivalent of "vi foo.c", then the execl call would be like : execl("/usr/bin/vi", "vi", "foo.c",NULL).

With fork and exec you now have all the tools to launch programs on Unix/Linux. First, fork off a new process from the current one. Then in the child process invoke exec to launch the new program.

Q: You should be familiar with the so-called shell programs. These are programs that run in a terminal window and accept commands typed by the user. Implement a small shell that repeatedly asks for the program name and then executes that program using fork() and exec; you can use wait() function to make the parent process wait for the child to terminate.

To simplify the problem, fill in the missing part of the following program:

#include< stdio.h >
#include< stdlib.h >
#include< unistd.h >
#include< string.h >
#include< sys/types.h >

#define NUM 1024
#define SIZE 50

int mystrtok(char *argv[], char* string){
	
	int i=0;
	char delim[]=" ";
	char *p;
	argv[0] = strtok(string,delim);
	while(argv[i]!=NULL){
		argv[++i] = strtok(NULL,delim);
	//	printf("%d is %s\n",i,argv[i]);
	}
	
	return 0;
}

int main(){

char str[NUM];
int status;
pid_t pid;
char * argv[NUM];


while(1){

	printf("\n$:");
	gets(str);
	status = mystrtok(argv,str);
	if(status!=0){
		printf("fail to get command!\n");
	}
	
	pid = fork();
	
	if(pid==-1) printf("fork failure!\n");
	else if(pid==0) {
		
	/*  Please fill in part of the program here.*/

		}
	else {
		wait();
		}
	}

}


Q:You may also like to think about this problem:
int main(int argc, char* argv[])
{
   fork();
   fork() && fork() || fork();
   fork();
}
How many processes are there altogether?

Helpful Documents


Student Feedbacks

If you have any advice and sugguestions about the lab or the course design, please let me know.:)