6.S081 lab1 write up
Preface
It is considered to be important to have an overview of Operating Systems. However, due to my laziness and the radio-building-oriented subject I major in, I hardly complete any courses about OSs.
After the spring festival, feeling still knowing little about OS and losing ability on computer programming, I picked up xv6 labs from MIT 6.S081 courses again, hoping by coping with them will be of help.
The hardest thing I came up with is not What to do but How to do and Why doing so works.
Lab: Utils
In this lab, I am assigned to finish a few UNIX utilities. It is not that difficult. All system calls can be found in user/user.h
.
Always check about hints before solving a task.
sleep
As a single program running on OS, you cannot count on yourself to sleep an exact period of time. Instead of using dead loops, you should use system call
s to acquire aid from the kernel.
After referring to the xv6 guide book, I find a system call named sleep()
, which I need to do next is to pack it up into a user program.
How to write a user program for xv6? By looking up other programs, I got ambiguous knowledge about it.
All user programs start executing from their main()
functions, arguments from console passed to the program from string array argv
. argc
is the number of arguments in argv
.
|
|
|
|
Programs can also take user inputs from stdin
, whose fd
is normally 0. It can be redirected to files or console outputs. scanf()
in stdio.h
takes input from it.
And functions like printf()
writes data to stdout
, whose fd
is normally 1. It can also be redirected to files.
If there is an error in your program and you want to print a message about what is going on, you should print it to stderr
whose fd
is normally 2. fprintf()
is used for this purpose.
So what we need to do is to pack up the system call sleep()
with a program realized in user/sleep.c
, and add it to Makefile
. The program should take its argument from argv
.
pingpong & primes
As I know, communicating between processes have mainly two ways:
-
Share memory to communicate
Using buffer or file that could be accessed by both sender and receiver. However, this usually leads to troubling issues like data racing that you should deal with it carefully. We call the buffer/file
Critical Section
. And there are mechanisms likemutex
andsemaphore
to prevent data racing or dirty data issues. -
Communicate with pipes, channels
Using pipes is much easier than dealing with shared memory in my point of view. When reading from an empty pipe, the process will be blocked until there are new data flushed in pipes or pipes being closed.
Pipes can be provided by OS, and some modern languages like
Go
have a language level support for pipes (referred asch
(channel) inGo
).
As for pingpong
, we can solve it by using 2 processes connected by 2 pipes, but be careful that if 2 process use printf()
at the same time, the output will be messed up.
As for primes, things get tricky a little. However, the link in the problem description had almost told you the answer.
I complete the task by realizing a void subprime(int* r_end)
function, which works like below:
I will change the graph’s engine into flowchart.js someday later…
print div"] B --> C1{"Is pipe's write end closed?"} C1 -- yes --> G["return"] C1 -- no --> C["int following <- read_end;"] C --> D["pipe p;
fork: subprime(p[READEND]);"] D --> E{"following % div == 0 ?"} E -- yes --> C1 E -- no --> F["p[WRITEEND] <- following"] --> C1
find
Just by adopting user/ls.c
, you can get a medium well find
program.
Files and directories in Linux are referred to as inode
s. Most of the file system layouts are like a tree with files/directories as nodes in it.
To access files in directories, you can use a fd
point to the path, and use read()
to read files/dirs under the directory, the data structure used to store child files/directories is struct dirent
.
Now that you are assigned to develop a find
program, you should use the function on child directories, so that the program can look up recursively.
xargs
In fact, this task is pretty simple, but the way xargs
works come out to be a little hard to understand.
The way xargs
works can be concluded into pseudo code like below:
|
|
Conclusion
Working on labs did give me an ambiguous impression about multithread programming, file systems and OS programming. There are still many jobs to be done.
My lab repository is -> here.