hw1

advertisement
Operating Systems (234120) – Spring 2007
(Homework 1)
Homework 1
Due date: Sunday 22.04.06, 12:30 noon
Teaching assistant in charge:

Alexander Landau
E-mails
regarding
this
exercise
should
be
sent
to
cs234120@csl1.cs.technion.ac.il with the subject line: cs234120hw1. Note
that this mail server will reject mails sent from non-Technion addresses (so
send your mails from t2, tx, or cs only).
Note 1: You must print your solution. Handwritten assignments will not be
accepted.
Note 2: In the dry part of this assignment you should assume that the fork()
system call always succeeds.
Question 1 (dry)
1. (8 points) What are all the possible outputs (i.e. text on the screen) of the
following program? Explain your answer.
int main()
{
int pid1 = fork();
int pid2 = fork();
int value = (pid1 != 0);
if (pid2 != 0)
{
if (pid1 != 0)
{
wait(&value);
value = WEXITSTATUS(value);
}
wait(&value);
value = WEXITSTATUS(value);
printf("%d ", value);
}
value *= 2;
printf("%d ", value);
return value;
}
2. (4 points) How many processes (including the original process in which
the function was called) are created during the execution of the following
function? Explain your answer.
void main()
{
for (int i = 1; i <= 10; i++)
{
1
Operating Systems (234120) – Spring 2007
(Homework 1)
fork();
if (i <= 6) fork();
}
}
Question 2 (dry)
(8 points)
Given the program below, draw the stack as it exists in memory when the
execution is at the line (2). Suppose that the ESP register was equal to
0x1000 when the execution was at line (1).
The figure you have to draw should look like the one on slide 5 of tutorial 2.
For every element on the stack, you should write:
 Its address.
 Its contents (variable name, register name, parameter name, constant
value, etc.). Be as specific as possible. For example, if some stack
element contains a constant, write the constant. If it contains an
address of some variable v, write “&v = 0xYYYY”, where YYYY (in hex)
is its address (if it is known), or write “&v” if its address is unknown.
 Its size in bytes.
int g(int x, char *s)
{
int a;
a = x + s[0];
(2)
return a;
}
void f(int x, int y)
{
int array[10];
char buffer[8];
array[0] = g(x+y, buffer);
}
void main()
{
(1)
f(3, 5);
}
2
Operating Systems (234120) – Spring 2007
(Homework 1)
3
Operating Systems (234120) – Spring 2007
(Homework 1)
Question 3 (wet, 80 points)
1. Introducion
In the preliminary assignment you learned the basic methods for changing
and compiling the Linux kernel. In this assignment you will use this
knowledge to make a more significant change to the functionality of the
kernel.
Your mission in this assignment is to enable processes to get some
information about their relationships with other processes. You’ll add several
new system calls to the interface of the Linux kernel. See the detailed
description below.
You should use VMware to simulate a virtual machine on which you compile
and run your "modified" Linux. Of course, those of you who want to work
directly on their computers and know how to do it are welcome to do so: you
will submit only the changed source files of the Linux kernel!
2. Detailed Description
You need to write code wrappers and internal system call implementations for
the following system calls (see the slides from tutorial 2). The description
below lists the wrappers as seen by the userspace code using them. The
system calls should be written according to the rules learned in tutorial 2.

int get_common_ancestor(int
#243)
p1, int
p2)
(system call
Description: Returns the first common ancestor p of the processes p1
and p2. The process p has the following properties:

p is an ancestor of p1 and of p2.

None of p’s children are ancestors of p1 and p2 simultaneously.
Note: “Ancestor” is a partial order relation, i.e. it is reflexive, antisymmetric and transitive. Specifically, a process is an ancestor of itself.
Returns -1 on failure; the first common ancestor PID on success.
On failure 'errno' should contain one of following values:

'ESRCH' (No such process): Either p1 or p2 are not valid PIDs.
An integer is a valid PID if it is strictly positive and there is a
process with that PID.
4
Operating Systems (234120) – Spring 2007
(Homework 1)

int get_path(int p1, int p2, int *array, int size)
(system call #244)
Description: Fills array with PIDs of processes in the hierarchy,
starting with p1, following with all processes up to and including the
first common ancestor of p1 and p2 (as defined by the above system
call), following with the path from that ancestor to p2. p1 is the first
entry of the array, p2 is the last entry and the common ancestor is
stored in the array only once (i.e. it is not doubled). p1 and p2 may be
the same process or one may be the ancestor of the other. In the
former case the array will contain just one element, and in the latter
case the array will contain the path from p1 to p2 (be it “upwards” or
“downwards” in the tree).
size is the length of the array (in elements, not in bytes). You must
not write more than size elements into it.
Returns -1 on failure; the number of elements filled in the array on
success.
On failure 'errno' should contain one of following values:

'ESRCH' (No such process): Either p1 or p2 are not valid PIDs.

'EINVAL' (Invalid argument):



size is 0 or negative.

array is NULL.

array can’t be written to (e.g. doesn’t belong to the
calling process address space).
‘ENOMEM’ (Out of memory): array is not long enough.
int are_brothers(int p1, int p2) (system call #245)
Description: Returns 1 if p1 and p2 are brothers (they have the same
direct parent process). Returns 0 if they are not.
Returns -1 on failure.
On failure 'errno' should contain one of following values:

'ESRCH' (No such process): Either p1 or p2 are not valid PIDs.
If several errors occurred (e.g. for get_path, p2 is not a valid PID and
size=0), you should return the error code listed first (i.e. ESRCH, for the
above example).
For each one of these code wrappers you should implement a system call
with the appropriate name (e.g sys_get_path for get_path). The return
value of the system call should be 0 for success, or the appropriate negative
error code. For example, if it is said that get_path sets errno to EINVAL
then sys_get_path should return –EINVAL.
5
Operating Systems (234120) – Spring 2007
(Homework 1)
Here is an example of the code wrapper for get_path (see explanation on
the next page). Follow this example to write the other code wrappers:
int get_path(int p1, int p2, int *array, int size){
long __res;
__asm__ volatile (
"movl $244, %%eax;"
"movl %1, %%ebx;"
"movl %2, %%ecx;"
"movl %3, %%edx;"
"movl %4, %%esi;"
"int $0x80;"
"movl %%eax,%0"
: "=m" (__res)
: "m" (p1), "m" (p2), "m" ((long)array), "m" (size)
: "%eax","%ebx","%ecx","%edx","%esi"
);
if ((unsigned long)(__res) >= (unsigned long)(-125)) {
errno = -(__res);
__res = -1;
}
return (int)(__res);
}
Explanation of inline assembler:
1) movl $244, %%eax – copy system call number to register eax.
2) movl %1, %%ebx - copy first parameter (p1) to register ebx.
3) movl %2, %%ecx - copy second parameter (p2) to register ecx.
3) movl %3, %%edx - copy third parameter (array) to register edx.
3) movl %3, %%esi - copy forth parameter (size) to register esi.
4) int $0x80 – system call invocation via interrupt 0x80.
5) movl %%eax,%0 – copy the value that was returned by the system
call to %0 (which is the first output operand).
6) : "=m" (__res) – output operand.
7) : "m" (p1), "m" (p2), "m" ((long)array), "m" (size) –
input operands.
8) : %eax,%ebx,%ecx,%edx,%esi – list of clobbered registers. Inform
gcc that we use eax, ebx, ecx, edx, esi registers.
You should read the following document for information about the commands
used in the preceding code segment:
http://www-106.ibm.com/developerworks/linux/library/l-ia.html
6
Operating Systems (234120) – Spring 2007
(Homework 1)
The Test program:
You must also write a test program called hw1_test.c that will verify the
correct functionality of the new system calls. The program should test all
system calls for both correctness and corner cases. Note that correctness
includes the right behavior for bad arguments.
Use VMware, like you learned in the preliminary assignment, in order to make
the following changes in the Linux kernel:

Put the implementation of the new system calls in the file
kernel/hw1.c (you will need to create and add this file to the kernel).
Update the makefile in that directory to compile your new file too. (Tip:
add it to obj-y)

Update entry.S (add the new system call table entries – use 243, 244
and 245).

Recompile and run the new kernel like you did in the preliminary
assignment.

Boot with your new kernel, and try to compile and run the test program
to make sure the new system calls work as expected.
Did it all? Good work, submit your assignment! 
4. Notes and Tips
 You are not allowed to use the syscall function to implement code
wrappers, or to write the code wrappers for your system calls using the
macro _syscall1. You should write the code wrappers according to
the example of the code wrapper given above.
 You should use the functions copy_from_user, copy_to_user, etc.
in order to copy data from user space to kernel space and vice versa.
Use the course book, Google or the man pages to find information about
these functions.
 '-EINVAL' stands for 'minus EINVAL'
 We will check your assignment with our own test program.
 Linux is case-sensitive. entry.S means entry.S, not Entry.s, Entry.S or
entry.s.
7
Operating Systems (234120) – Spring 2007
(Homework 1)
5. Submission
The submission of this assignment has two parts:

An electronic submission – you should create a zip file (use zip only, not
gzip, rar, 7z, …) containing the following files. Make sure your zip file
contains only the files below without any directories in it.
a. hw1.c – contains the kernel code you’ve written.
b. entry.S – contains the syscall table.
c. hw1.h – contains the implementation of the syscall wrappers.
d. hw1_test.c - contains your test program (which, obviously,
#include-s “hw1.h”)
e. A file named submitters.txt which includes the ID and name of
the participating students. The following format should be used:
Bill Gates 123456789
Linus Torvalds 234567890
Steve Jobs 345678901

A printed submission:
a. A printed solution of questions 1 and 2 (dry).
b. A printout of the source code including your test program. For
existing Linux files (such as entry.S), only the changes should
be printed. We will not check assignments that have full
printouts of kernel source files!
c. The output of your test program.
Good Luck,
The course staff
8
Download