TIP
- Please remember to setup your VPN if you try to connect to EOS machines from off-campus locations.
New in Fall 2020: you can now remote login to Arch/EOS via our new Virtual Labs- New in Fall 2024: The Virtual Labs URL has changed to http://computing.gvsu.edu
Introduction to Unix and System Dev Tools
The purpose of this assignment is to re-familiarize yourself with UNIX commands and system calls, with the syntax and use of C library functions, and with some of the programming utilities and development tools that will be used during the course of the semester. This lab should largely be review material from the Linux lab component of CIS163 and CIS361 Systems Programming.
This lab exercise concentrates on tools and utilities available on any Linux-based system. Many of the utilities used in this exercise have graphical equivalents available on our systems. Consult your Linux guide for more information on using the Gnome GUI, use the online help, or just ask the person sitting next to you.
Objectives
Upon completion of this lab assignment students will:
- become familiar with UNIX commands,
- become familiar with the syntax and use of C library functions and system calls.
- be able to use a number of programming utilities and development tools.
- be able to distinguish system calls from library functions
Activities
- Perform the experiments described below, demonstrate your knowledge of the material by answering the numbered questions in this handout.
- This exercise can be completed as a group assignment (i.e. work together with another student if you can)
- Submit a detailed and typed lab report (one per group) to the number questions and all requested output (files, source code, etc.). Be sure the report is written such that it will be easy for the grader to find specific details:
- Include the names of both students in the group
Important
In your lab report, be sure to copy the original question prior to writing your answer
Online Help
Most Unix systems have online manual pages installed. In a Linux-based system, these manual pages can be found under the directory /usr/share/man
. Under this directory you will find subdirectories: man1
, man2
, ... each corresponds to one section of manual pages. Under one of these (sub)directories, the manual page for a certain Linux command, a system call, or a library subroutine is stored as a (flat) text file. Thus, in a typical Linux system one can find thousands of such files
Section | Contents |
---|---|
1 | User Commands |
2 | System Calls |
3 | Library Subroutines |
5 | File Formats |
8 | System Administration |
For this course, you will primarily reference sections 2 and 3. This large number of files may be daunting at first, but with sufficient practice of using the man
command, Linux man pages actually become readable.
The man
command
The following commands are a starting point for productively using the Linux man pages:
man man
: describes how to use the man commandman
numintro
: displays information from the introduction to the requested section.man
topic: displays information on the requested topic.man
num topic: displays information on the requested topic in the requested section. This syntax is needed when a command is found under several sections, but you need the one from a particular section.man -k
keyword: lists manual pages which contain the requested keyword in their synopsis
For instance, to display the introduction to the system calls section:
man 2 intro
to display the manual page of the fopen
subroutine
man fopen
to display the manual page(s) that deal with password:
man -k password
man -k password | grep '(3)' # filter only those in section 3
Note: Unix man pages are also available online in various formats.
TIP
When you open a manual page, the bottom of the screen should give you a quick help highlighted summary:
Manual page XXXX(yyy) line zzz (press h form help or q to quit)
The default pager program to browse man page is less
and it understands several keyboard shortcuts to navigate your way around the document, among these shortcuts are:
Key | Description |
---|---|
f | scroll forward |
b | scroll backward |
/pattern | Search for a text (pattern) within the manual page |
n | search again (forward) |
N | search again (backward) |
- (2 pts) Browse a number of manual pages of your choice from section 1, 2, and 3. Observe that they contain common "headings" (NAME, SYNOPSIS, DESCRIPTION, SEE ALSO). Most manual pages in Sections 2 (System Calls) and 3 (Subroutines) also include RETURN VALUE and ERRORS. Briefly describe the purpose of any two "headings"
- (2 pts) Describe the difference between the Unix user command
time
and the System calltime()
.
TIP
- Towards the end a manual page you may also find C coding example describing how to use the function/system call
- The SEE ALSO section shows other manual pages related to the current one you are browsing. Sometimes, more detailed information for your programming work can be found in the other manual pages.
Useful Unix Commands
You should be fluent with all file handling commands and familiar with the various options these commands provide. In particular, you should know how to use:
Command | Description |
---|---|
cp | copy file |
mv | move or rename a file/directory |
rm | remove (delete) a file |
mkdir | make a new directory |
rmdir | remove (delete) a directory |
ls | list the contents of a directory |
cd | change to another directory |
pwd | print the name of the current working directory |
chmod | change access permissions of files and directories |
cat | print a file to stdout |
more/less | print a file to stdout, a screenful at a time |
Also, familiarize yourself with these miscellaneous commands:
Command | Description |
---|---|
script | record a terminal session |
telnet | login to a host (telephone network protocol) |
ssh | secure login to a host |
lpr | send a file to a printer |
grep | pattern match a string in files |
Note: the desktop interface has a Windows-like file manager that graphically facilitates many of the above file tasks.
If you are unfamiliar with any of these commands, consult an introductory UNIX text or user guide (like Linux in a Nutshell by Siever, et al.). Alternatively, you can utilize the Help system as described above.
Include Files / C Header Files
Manual pages in sections 2 and 3 show the name of header files to include in a C program. A header file defines function prototypes, macros, data structures, and other useful components.
For instance, the SYNOPSIS of opendir
shows the following include lines:
#include <sys/types.h>
#include <dirent.h>
The physical locations of these two header files are /usr/include/sys/types.h
and /usr/include/dirent.h
. Additionally, the directory /usr/include/bits
will be frequently referenced as well. However, some compilers may install them at a different location and you can check the actual directory paths by typing:
clang -print-search-dirs | tr ':' '\n'
# gcc -print-search-dirs
(1 pt) What is the meaning (not its integer value) of the stream-based
SEEK_CUR
macro?Start by using a keyword search on the man pages to find possible
seek
function calls (either from section 2 or 3)bashman -k seek
Use the man pages to discover which include files are referenced by those function calls.
Write a C code that includes the header file(s) you discovered in the previous step
c#include <______.h> int main() { /* empty main which does nothing */ return 0; }
Compile the above C program with following options
bashgcc -E -CC -dD the-name-of-the-above-C-file.c | less # OR use grep gcc -E -CC -dD the-name-of-the-above-C-file.c | grep SEEK_CUR
Use the
less
search shortcut (the same '/' shortcut used for word search within a man page) to search forSEEK_CUR
or usegrep
as shown.
(1 pt) What is the command to list the contents of a directory in "long mode", including hidden files?
(1 pt) What is the command syntax to make a directory readable/writable only by you?
Program Development
The typical program development cycle consists of Edit-Compile-Run-Debug sessions that repeat until the program functions as specified.
Edit
There are several text editors available on the system. Among these editors, vi is always available on every Unix system. Current Linux distributions provide vim (Vi IMproved) as part of the basic utilities. Another powerful text-based editor is emacs. Some of the choices of graphical text editors are: gvim, gedit, kate, kwrite)
Compile
Use either clang
or gcc
to compile your C programs. (Use clang++
or g++
for C++). Check out the man pages for useful command line options. In addition, always enable the "all" warning option (i.e -Wall
). Sometime, you may also need to link your program with specific libraries (e.g. use the -lm
flag to link with the math library). One of the biggest differences between C and C++ or Java is the C standard I/O library, so you should also do a man on printf()
for output and scanf()
for input to understand C-style I/O.
The basic command line for compiling a C or C++ program:
clang -Wall -g name-of-your-C-program.c
# gcc -Wall -g name-of-your-C-program.c
clang++ -Wall -g name-of-your-C++-program.cpp
# g++ -Wall -g name-of-your-C++-program.cpp
# Use -lm if you need to link with the math lib
clang -Wall -g name-of-your-C-program.c -lm
gcc -Wall -g name-of-your-C-program.c -lm
Run
Unless the -o option is specified, a successful compilation of a C program will generate an executable file a.out
. To run this program you will type either
a.out
or
./a.out
depending on how your PATH is configured. Recall that the prefix "./" refers to the directory you are currently in.
Debug
Use gdb
to debug your programs. Debuggers can be very useful, not only to determine the source of problems in a program, but also to understand program execution better. Remember to compile your C (or C++) programs with the -g
option to inform the compiler to include debugging information in the executable. Use ddd
for a graphical frontend to gdb
.
The following list shows some useful (sub)commands of gdb
:
Command | Description |
---|---|
help | self-explanatory |
b | set a breakpoint (to stop program execution at the specified location or function name) |
l | show source code listing around the current line |
n | continue to the next line in a program (steps over function calls) |
s | step to the next instruction in a program (steps into function calls) |
run arg(s) | run the program and pass arg(s) as the command line arguments of the program. |
p | display (print) the value of a variable |
w | display (watch) the value of a variable whenever it changes |
bt | display (backtrace) the current program execution stack |
Sample Program #1
[Gist]API rate limit exceeded for 54.209.88.255. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
- (2 pts) Perform the following steps:
Create the above program
Compile the program (remember to include debugging flag and link all necessary libraries)
bash# This command is incomplete. You must include the math lib clang -Wall -g name-of-your-program.c # gcc -Wall -g name-of-your-program.c
Run the program (without a debugger)
bash./a.out
Start the debugger on your program (
gdb a.out
).bashgdb ./a.out
Do the following in the debugger session:
Set a breakpoint at the function
main
bash(gdb) b main
grab a screenshot of the debugger session
Run your program again, and step through it. When running the debugger
bash(gdb) run (gdb) n # continue to the [n]ext instruction
WARNING
you may receive a warning about missing debuginfos (which can be ignored)
Missing separate debuginfos, use debuginfo-install glibc-2.xxxxxxx.x86_64
Use the debugger to print the value of
num
before and after it changesbash(gdb) p num
grab another screenshot of the debugger session
quit the debugger
bash(gdb) q
Print/submit the screenshots as part of your lab reportß
Dynamic Memory Debugging
In the following section we will perform a more specific kind of debugging: (dynamic) memory debugging. In particular, we want to use tools that allow us to examine a program's use of memory while it is executing (hence "dynamic"). Proper use of these tools allows us to catch common memory errors (memory leaks, attempting to access de-allocated memory, attempting to access beyond allocated memory, etc.).
Finding Memory Leaks (Sample Program #2)
[Gist]API rate limit exceeded for 54.209.88.255. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
Study the above code until you are certain of what it does. If necessary, open the manual page of malloc
to learn more about the system calls. Although it appears to run correctly, there is a memory leak within the loop that will cause a problem if the loop is executed a sufficient number of times. There is also another apparent instance of "unrecovered" memory; it occurs outside the loop and is a less serious problem.
We will use valgrind to detect memory problems. Type the following at the command prompt:
# Be sure to compile with -g
gcc -g name_of_your_program.c
valgrind --leak-check=full ./a.out
It takes some practice and good guessing to understand the errors identified in valgrind output.
Run the program and be sure the loop executes several times before typing "quit". Use the line numbers provided valgrind and your understanding of the code and the pattern of memory losses to determine the source of error.
(2 pts) Describe precisely (nature of problem, location) the memory leak(s) in the above program.
- Fix the problem(s) by adding necessary
free()
call(s). But, don't change themalloc()
calls, mark your modification(s) with readable C comments - Add your name(s) as a C comment at the beginning of source code.
- Print and submit the modified source code
- To confirm that the memory leaks have been fixed, use
valgrind
again on your revised code.
- Fix the problem(s) by adding necessary
Execution Debugging
The next utility program we will use in this lab is stracewhich is designed for profiling flow of execution through a program and its use of system/library calls.
TIP
Please read the man pages to discover strace operation and use
Run strace on the original Sample 2. You will see voluminous output generated by strace
bashstrace ./a.out
Read the manual again to discover the command-line option to get a less cluttered output in order to answer the next question below. Hint: look for "Filtering" option.
(1 pt) How many times is the
write()
system call invoked when running Sample 2?. Note: run several different experiments, then try to answer as a formula.(1 pt) Use the example the source code and experiment to answer the question: what is the primary C library subroutine that causes the
write()
system call to be invoked by Sample 2?