Lab Manual-CSE 325 (Operating System) Department of Computer Science & Engineering East West University Lab 1: Introduction

to Linux Purpose: The hardest program you will ever write is Hello World. You have to be comfortable with a new language, tools and build environment. Once you have these skills, then you can get to some meaning full programming. In the operating system labs, all programming will be done under the Linux operating system, using standard programming tools for that environment. Linux is a free operating system, available for all to download and use with no cost. Linux itself is about a decade old, but in conjunction with a set of free utilities from the GNU project, behaves like a member of the UNIX family of operating systems. UNIX has been the standard for research institutions and the computer industry in general for decades. As a matter of pride it is expected that you, as a Computer Science student, will learn to use it. It is very much in your best interest to get used to Linux as early as possible, since it will be your primary tool for learning most operating system concepts. Tutorials on Linux are available all over the Internet, Google for "Linux tutorial" and find one that suits you if this introduction is not enough for you to become comfortable. Objectives:  Getting a quick introduction to Linux  Writing ‘Hello World’ program under Linux  Using the ‘Make’ tool to simplify the compile process Procedure: Linux has a Graphical User Interface much like Windows, but also has an extremely powerful and all-encompassing command line interface that allows you to interact more quickly and efficiently with the system. This looks similar to a DOS style command line interface. To access this interface look under “accessories” from the drop down menu in the top left corner of the screen on the ubuntu desktop or by clicking the black “konsole” icon in the kubuntu desktop. This will pop up a window known as a "Terminal." Inside your terminal window is where you enter your commands. (note, other books and environments might call this the “console” or “konsole”) To save time typing, use the history feature of the command line by using the up arrow button to scroll through recent commands. Also, when typing file names, you can just type the first few letters and then press TAB. This will fill in the rest for you. There are so many time savers for command line interfaces, but these two are the most common. (Windows command line has now added this feature too) Basic Commands:  ls (list the contents of your current directory. similar to ‘dir’ under MS -DOS/Windows)  cd a (move into the directory a)  cp a b (copy file a to file b)  mv a b (move file a to b, removing the original)  rm a (remove or delete file a)  mkdir a (create a directory called a)  rmdir a (remove empty directory called a)  rmdir -r a (remove a directory and its files called a)  man command (display online help on command)  man -k word (search for help on word) These commands have many options associated with them, and you should use ‘man’ (manual) to see how to use them. There are literally hundreds of additional commands commonly available, as well as a

Md. Shamsujjoha

CSE, EWU

Page 1 of 9

large number of options available for the commands presented here. It is highly recommended that you take some time to experiment with these commands, read some documentation, and get to know your environment. With the decades of histories, nearly everything you might want to do has been done and automated by some other developer and included in the plethora of UNIX commands. Learning as many as you can will make your life later on easier and easier. Start early. G++: The very popular (and free) compiler for UNIX systems is gcc. When used to compile C++ programs, it is generally invoked as g++. Throughout this course we will be using g++ for compilation. In its simplest invocation, we only need to call it with the name of the program we are trying to compile. In this example we will compile "hello.cc". (Note that the standard filename extension for C++ files is now ".cc" rather than ".cpp"). Here we will try to compile the following: // hello.cc – version 1 #include <iostream.h> void main(){ cout << “Hello World!” << endl; } Now we save that file from your choice of text editor (emacs, vi, gedit, etc) and try to compile in the terminal by typing: > g++ hello.cc In file included from /usr/include/c++/3.2/backward/iostream.h:31, from hello.cc:1: /usr/include/c++/3.2/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <x> header for the <x.h> header for C++ includes, or <sstream> instead of the deprecated header <strstream.h> . To disable this warning use command line option -Wno-deprecated. hello.cc:6: `main' must return `int' Sadly, our program failed to compile, and g++ produced a lot of (somewhat) mysterious output when we tried to compile it. Let's look more closely at what happened. This is really just one long warning (note at the end of the third line there it says "warning"). What this really means, in very complicated language, is that we should not have had "iostream.h", but rather "iostream", the new standard. Now let's look at the second bit of output. hello.cc:6 `main' must return `int' Unlike Microsoft's version of C++, g++ enforces the standard practice of having the main function be of type "int." This integer being passed back generally is used to report success, failure or an error number to the terminal. This is useful when programs call other program similar to the return value of a function call.

Md. Shamsujjoha

CSE, EWU

Page 2 of 9

So, we change main() to return type int and try again and get following output: > g++ hello.cc hello.cc: In function `int main()': hello.cc:5: `cout' undeclared (first use this function) hello.cc:5: (Each undeclared identifier is reported only once for each function it appears in.) hello.cc:5: `endl' undeclared (first use this function) How could "cout" be undeclared? The error is caused because G++ enforces the new C++ specification regarding ‘namespaces’. Most languages require namespaces to differentiate identifiers within a given context. Meaning, we need to be specific about which identifiers belong to which classes (or packages) to avoid collisions, or ambiguity. This is beyond the scope of this lab, but to see how different languages deal with namespace, there is more here: http://en.wikipedia.org/wiki/Namespace_%28computer_science%29 There are two ways to solve this compile error: #include <iostream> int main(){ std::cout << “Hello World!” << std::endl; return 0; } Now we have removed any ambiguity as to what namespace ‘cout’ and ‘endl’ belong. But a cleaner solution is to just declare it from the start by doing: #include <iostream> using namespace std; int main(){ cout << “Hello World!” << endl; return 0; } This basically tells the compiler to use ‘std’ as the default namespace for the identifiers. Regardless of your choice on this issue, let us see if this fixes our simple program: > g++ hello.cc > Nothing happens. Believe it or not, this is a good thing. (A rule of thumb under UNIX is that if no output was generated, everything worked correctly.) However, we still have not run our program. When compiling, g++ creates executable files named "a.out" by default. If you don't like this default choice (and who does?), then you can add the "-o" command line parameter to pick your own filename, like this, > g++ hello.cc -o hello (Note also that unlike Windows, no ".exe" extension is needed.) Now we have a file called "hello" in our current directory that when executed will (presumably) print out our friendly greeting. > ./hello Hello World! >

Md. Shamsujjoha

CSE, EWU

Page 3 of 9

At this point you should be able to use g++ from the command line to compile a C++ program. However, to help you through some of the complicated concepts that will come up in this course,we are going to enforce the use of four additional options when compiling "-W", "-pedantic", "-Wall" and "-Werror". -W is an option (also called a flag) for g++ that is given to the program on the command-line. It says, "I'd like you to warn me about all of the simple mistakes that people might make." This lets g++ do some of the checking for you that would otherwise cause you lots of time and trouble. (Remember, warnings that are caught are often logic errors that you don't have to fight! This is a very good thing.) -pedantic means that g++ will turn off some of the features in the g++ compiler that are not part of the C++ standard. For the most part these are fairly esoteric, but there are a couple common things that people in this course would do with g++ that are not actually allowed by the standard,so we enforce this flag in an effort to prevent you from learning non-standard (bad) habits. -Wall says "If I do anything in this program that is really odd, warn me." C++ has a long long list of things that could possibly indicate a programming mistake, but by default many of them are not checked when compiling. Adding -Wall ensures that many of the more complex things it can warn you about will be reported. (It is like having a very picky set of eyes checking over your program for you. This is a good thing.) -Werror is related to the other flags in that they all deal with warnings. Unlike the others, it doesn't enable additional warning messages. Instead -Werror tells the compiler "If you ever feel like warning me about anything, consider that an error and do not compile any further." This way even if you wanted to ignore the warnings, you would have to find a way to convince the compiler that you really know what you are doing. We are enforcing the use of these to flags so that your programs are more likely to work on complicated input, and because there really is no reason to have any warnings in a well written program. For your home programming projects, we will compile your submissions with -Wall and -Werror, so you should get used to using them now. So the general command line you will be using this quarter when compiling by hand is: > g++ -W -Wall -Werror -pedantic myprog.cc -o myprog You probably want to memorize this, and use it in your make files. Make Makefiles are a simple way to organize code compilation. This introduction does not even scratch the surface of what is possible using make, but is intended as a starters guide so that you can quickly and easily create your own makefiles for small to medium-sized projects. (Note, Ant was developed for java builds because makefiles can get pretty ugly to read. So even a very complex build.xml file will be easy to navigate compared to make. They do the same things, just with different formatting.) The syntax for a Makefile: The make utility uses a Makefile that specifies the rules for maintaining programs up to date based on changes done to files. A Makefile to keep C/C++ programs up to date must specify the order in which to compile the source code distributed in different files. A rule to compile (not link) the source code in a file sort.cpp is specified as follows: sort.o: sort.cpp sorting.h $(COMPILE) sort.cpp A typical Makefile rule can be described as follows: target: <space separated list of dependencies for the target> <TAB> <The action to perform whenever the target is out of date>

Md. Shamsujjoha

CSE, EWU

Page 4 of 9

In the example rule above that is used to keep up to date the file sort.o, the different components are: target: sort.o list of dependencies: sort.cpp sorting.h action: $(COMPILE) sort.cpp Whenever any of the files listed as dependencies (sort.cpp and sorting.h) is modified and the user enters the command to "make", then the make utility will perform the action (to compile) because the target (sort.o) is out of date relative to the its dependencies. To specify an order on the actions to be taken, you can have one rule depend on another rule. For example, in order to link and thus create an executable program, the different source code files must first be compiled. So, the following rule can be used to do this: sort: sort.o insertion_sort.o selection_sort.o misc.o $(LINK) -o sort sort.o insertion_sort.o selection_sort.o misc.o This rule states that in order to perform the action (link), that the dependencies (the object files) must be present. If any of the dependencies are not present (or are newer than the target), then the rules that refresh those dependencies will be activate. Say that sort.cpp file was modified, then when the make facility tries to make sort, it goes to the rule that makes sort.o. That rule states that sort.o depends on sort.cpp. Make determines that the timestamp of sort.o is older than the timestamp of sort.cpp, so it performs the action (compile) to bring up to date the target. This is done for each of the dependencies of sort and once all are checked, the action (link) is performed, if necessary. The next section shows how all of this works. A Simple Example: Let's start off with the following three files, hellomake.c, hellofunc.c, and hellomake.h, which would represent a typical main program, some functional code in a separate file, and an include file, respectively. //hellomake.c #include "hellomake.h" int main() {
//call a function in another file

//hellofunc.c #include <stdio.h> #include "hellomake.h" void myPrintHelloMake() { printf("Hello makefiles!\n"); }

//hellomake.h // example include file #ifndef MY_HELLO #define MY_HELLO void myPrintHelloMake(); #endif

myPrintHelloMake(); return 0; }

Normally, you would compile this collection of code by executing the following command: gcc -o hellomake hellomake.c hellofunc.c -I. This compiles the two .c files and names the executable hellomake. The -I. is included so that gcc will look in the current directory (.) for the include file hellomake.h. Without a makefile, the typical approach to the test/modify/debug cycle is to use the up arrow in a terminal to go back to your last compile command so you don't have to type it each time, especially once you've added a few more .c files to the mix. Unfortunately, this approach to compilation has two downfalls. First, if you lose the compile command or switch computers you have to retype it from scratch, which is inefficient at best. Second, if you are only making changes to one .c file, recompiling all of them every time is also time-consuming and inefficient. So, it's time to see what we can do with a makefile.

Md. Shamsujjoha

CSE, EWU

Page 5 of 9

The simplest makefile you could create would look something like: #Makefile 1 hellomake: hellomake.c hellofunc.c gcc -o hellomake hellomake.c hellofunc.c -I. If you put this rule into a file called “makefile” and then type make on the command line it will execute the compile command as you have written it in the makefile. Note that make with no arguments executes the first rule in the file. Furthermore, by putting the list of files on which the command depends on the first line after the “:”, make knows that the rule hellomake needs to be executed if any of those files change. Immediately, you have solved problem #1 and can avoid using the up arrow repeatedly, looking for your last compile command. However, the system is still not being efficient in terms of compiling only the latest changes. One very important thing to note is that there is a tab before the gcc command in the makefile. There must be a tab at the beginning of any command, and make will not be happy if it's not there. In order to be a bit more efficient, let's try the following: #Makefile 2 CC=gcc CFLAGS=-I. hellomake: hellomake.o hellofunc.o $(CC) -o hellomake hellomake.o hellofunc.o -I. So now we've defined some constants CC and CFLAGS. It turns out these are special constants that communicate to make how we want to compile the files hellomake.c and hellofunc.c. In particular, the macro CC is the C compiler to use, and CFLAGS is the list of flags to pass to the compilation command. By putting the object files -- hellomake.o and hellofunc.o -- in the dependency list and in the rule, make knows it must first compile the .c versions individually, and then build the executable hellomake. Using this form of makefile is sufficient for most small scale projects. However, there is one thing missing: dependency on the include files. If you were to make a change to hellomake.h, for example, make would not recompile the .c files, even though they needed to be. In order to fix this, we need to tell make that all .c files depend on certain .h files. We can do this by writing a simple rule and adding it to the makefile. #Makefile 3 CC=gcc CFLAGS=-I. DEPS = hellomake.h %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: hellomake.o hellofunc.o gcc -o hellomake hellomake.o hellofunc.o -I. This addition first creates the macro DEPS, which is the set of .h files on which the .c files depend. Then we define a rule that applies to all files ending in the .o suffix. The rule says that the .o file depends upon the .c version of the file and the .h files included in the DEPS macro. The rule then says that to generate the .o file, make needs to compile the .c file using the compiler defined in the CC macro. The -c flag says to generate the object file, the -o $@ says to put the output of the compilation in the file named on the left side of the “:”, the $< is the first item in the dependencies list, and the CFLAGS macro is defined as above.

Md. Shamsujjoha

CSE, EWU

Page 6 of 9

As a final simplification, let's use the special macros $@ and $^, which are the left and right sides of the :, respectively, to make the overall compilation rule more general. In the example below, all of the include files should be listed as part of the macro DEPS, and all of the object files should be listed as part of the macro OBJ. #Makefile 4 CC=gcc CFLAGS=-I. DEPS = hellomake.h OBJ = hellomake.o hellofunc.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ) $(CC) -o $@ $^ $(CFLAGS) So what if we want to start putting our .h files in an include directory, our source code in a src directory, and some local libraries in a lib directory? Also, can we somehow hide those annoying .o files that hang around all over the place? The answer, of course, is yes. The following makefile defines paths to the include and lib directories, and places the object files in an obj subdirectory within the src directory. It also has a macro defined for any libraries you want to include, such as the math library -lm. This makefile should be located in the src directory. Note that it also includes a rule for cleaning up your source and object directories if you type make clean. The .PHONY rule keeps make from doing something with a file named clean. #Makefile 5 IDIR=. CC=gcc CFLAGS=-I$(IDIR) ODIR=obj LDIR =../lib LIBS=-lm _DEPS = hellomake.h DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS)) _OBJ = hellomake.o hellofunc.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ)) $(ODIR)/%.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS) hellomake: $(OBJ) $(CC) -o $@ $^ $(CFLAGS) $(LIBS) .PHONY: clean clean: rm -f $(ODIR)/*.o *~ core $(IDIR)/*~ So now you have a perfectly good makefile that you can modify to manage small and medium sized software projects. You can add multiple rules to a makefile; you can even create rules that call other rules. For more information, at the Linux prompt, type "info make" (without the quotesof course). This guide was partly based on the documentation found there.

Md. Shamsujjoha

CSE, EWU

Page 7 of 9

Debugging: Ok, now we can write code, build it and run it. What happens next? Write code that does more than simply write Hello World to the terminal. That is when the errors really start to arise. A debugger is really just a program that runs other programs and allows the user to examine the state of variables as it runs. The GNU debugging tool is called GDB and it has more features than you will ever need for this course. First you must tell the compiler that you intend to use the debugger by adding the –g option. So you for example you type: > g++ hello.cc –g –o hello if no errors, then launch gdb by: > gdb hello GDB commands: When gdb starts, your program is not actually running. You must start it and provide any command line arguments you need. You will be prompted for command by the debugger. The main commands are:          run command-line-arguments (starts your program) break place, or a line number (creates a breakpoint; the program will halt when it gets there) delete [N] (removes breakpoint number N. Leave off N to remove all breakpoints.) help [command] (provides a brief description of a gdb command or topic) step (executes the current line of the program and then stops) next (like step, but will exucute the function call if there is one on the current line) finish (keeps doing nexts, until reaching the end of the current function) continue (continues regular execution of the program until a breakpoint is hit or the programs quit (leave the debugger)

Basically, gdb will help you find those nasty pointer problems, or the variables you forgot to initialize. If you can see the state as it runs, these problems can be found out – before it crashes! If you have a problem, use the debugger BEFORE asking your Instructor. Find the full manual at: http://www.gnu.org/software/gdb/ Deliverable: You should submit your lab works according to the style guide, on or before due dates and via email. Create a Folder named as “LAB.X_ID.201Y-AB-CD-EFG”. Here, X is lab number. For example, if you are submitting lab: 3’s work(s), the value of X must be 3; then append your EWU ID No. You should mail the compressed version of this folder. The folder should contain:  Corresponding make file  A readme text file  The code(s) This lab may seem elementary to those comfortable with Unix/Linux tools and compilers. If you are not comfortable with these commands and compile tools you should do more experimenting and practice than just this lab, without this basic skill set you will certainly be fumbling along when the labs get more complicated. Remember, in general, I will simply type ‘make’ to compile and run your code. If there are errors, I will not be looking around trying to fix your build, SO BE AWARE.

Md. Shamsujjoha

CSE, EWU

Page 8 of 9

Readme.txt: Every lab you submit for marking must include a “readme.txt” with your work. Pay attention to the format, you must have an entry for every heading. A sample is provided below: Name: Md. Shamsujjoha Student #: 2013-03-60-005 -----------------------Assignment: [lab6] Clock ---------Description: ----------C implementation of the Clock program. keep it short and concise. My assignment solution consists of the following files: - a.cpp - a.h - b.h - a.exe Running my solution: ------------------You can run my assignment as follows: > make run_target IDE/Compiler: -----------Microsoft Visual C++ 6.0 Running procedure: ----------------... Assumptions: ----------My program can't handle empty lines, but takes care of spaces, dots and other characters. Conclusions/Remarks: ------------------I had problems implementing the ... but I solved this problem by doing ... Errors/Bugs: ----------One error I can not fix/find is ... There might be a bug in function ... You can see it by running the program with the following parameters ...

Reminder: No student will be allowed to enter into the lab without completion of the previous lab work(s). I vigorously opposed to the academic dishonesties, as it seriously detracts from the education of honest students. In case of any problem, inconsistency and/or errors knock your Instructor. I am always there to help you and to remove your confusions.
Thanks, Md. Shamsujjoha (Lecturer, CSE, EWU) Email: msj@ewubd.edu or dishacse@yahoo.com Sept-13, 2013

Md. Shamsujjoha

CSE, EWU

Page 9 of 9