CS计算机代考程序代写 compiler Last updated: February 8, 2021

Last updated: February 8, 2021
Carleton University School of Computer Science
COMP 3000 (WINTER 2021) OPERATING SYSTEMS TUTORIAL 3
Tasks/Questions – part 1
gcc -O2 -static -o 3000memview.static 3000memview.c
Then compile a dynamically linked version:
1. By default, gcc-produced binaries are dynamically linked (so at runtime they will require dynamic libraries to be present on the system). To compile a binary that is statically linked (so it has no
external runtime library dependencies), instead do this:
gcc -O2 -z lazy -o 3000memview.dynamic 3000memview.c
How does the size compare between 3000memview.static and 3000memview.dynamic?
The static one should be much bigger than the dynamic one, since it has all required libraries included. The actual size would vary with many factors (e.g., the compiler/linker version). In
my case, it’s 871840 (static) vs 17128 (dynamic).
2. See what library calls the dynamic version produces by running
dynamic.log ./3000memview.dynamic (then you can check libcalls-dynamic.log). Do the same for the static version. What is your observation?
The dynamic version should produce a few library calls. If interested, you can also show library calls and system calls altogether with ltrace -s (those starting with SYS_ are system calls). This is another way you can match library calls with system calls.
If you run it for the static version, you’ll see ltrace complain about “Couldn’t find .dynsym or .dynstr” as the static one does not have dynamic symbols, as expected.
3. See what system calls the dynamic version produces by running strace -o syscalls- dynamic.log ./3000memview.dynamic (then you can check syscalls-dynamic.log). Do the same for the static version. Which version generates more system calls? From which part of the code?
As explained last class, the dynamic version generates more, in this specific case, because it needs to read and load the libraries into memory for invocation (so, from the beginning of the code).
4. Using ldd, what dynamic library dependencies does the top command have? Note that you must specify the full path to top.
Just use , and what you see on the right are the results of the search
ltrace -o libcalls-
ldd `which top`
(including but not limited to ).
5. Now, try to run ./3000memview.dynamic multiple times as needed and observe its output (leave libcalls/syscalls for now). Why are the addresses inconsistent between runs?
Simple answer: because they are just virtual addresses, determined by the OS.
Accurate answer: because of ASLR (address space layout randomization), as mentioned briefly during the lecture.
You can disable it (not recommended for systems in real use) with:
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
$LD_LIBRARY_PATH

6. Roughly where does the stack seem to be? The heap? Code? Global variables?
(hints: recall the memory image layout of a process; local variables go to the stack; initialized data and global variables go to the data segment, data allocated at runtime go to the heap.)
Local variables are: lmsg and buf, so &lmsg and &buf (the location of them) are around the stack. The value of buf[0] (dynamically allocated) is in the heap. We will discuss it in a bit more detail.
7. Change each call to allocate more than 128KiB. What happens to the values of sbrk()? Why? (hint: use again). Note: KiB (kibibytes) = 210 = 1024 bytes.
malloc()
strace
When the amount to allocate exceeds a certain threshold uses to allocate memory instead. This threshold is
, or more simply the environment variable easily try it out by changing the environment variable.
stops using sbrk() and when calling
. You can
malloc()
mmap()
M_MMAP_THRESHOLD
mallopt()
MALLOC_MMAP_THRESHOLD_
Tasks/Questions – part 2
1. Implementredirectionofstandarderror(stderr).Itwouldbeverysimilartothestdoutredirection already implemented.
For simplicity, instead of using “2>” as the operator, you can choose another single- character operator so that the added code matches that of redirection of standard output. See code.
2. Why are lines 207-210 there (the check for pid == -1)?
This ensures the parent does not wait for nothing (e.g., if child has already terminated) and still reports status based on the failed call. Note that wait() is called in both the signal handler and run_program().
3. Byusingstrace(oranothertoolofyourchoice)andreadingthecode,identify4ormorelibrarycalls in 3000shell that invoke system calls and explain what the system calls are used for therein.
Of course there are more than 4. Examples: sigaction() calls to register the signal handler function. calls write() to output to stdout. calls read() to read from stdin. calls to get a file descriptor for (opening) a directory. readdir() calls to read directory entries (dentry).
rt_sigaction()
printf()
fgets()
opendir()
openat()
getdents64()
2