Lecture 1. Introduction And Example
课堂板书
- OS Design
- Hands-on experience(xv 6)
- OS purposes
- abstract hardware
- multiplex
- isolation
- sharing
- security
- performance
- range of uses
- OS organization
- cpu、ram、disk、network
- user space: text editor(vi)、complier(CC)、shell(sh)
- kernel: file system、processes、 memory alloc、access control
- API-kernel
fd = open("out", 1);
write(fd, "hello\n", 6);
pid = fork();
-
Why hard/interesting?
-
unforgiving
-
tensions
- efficient - abstract
- powerful - simple (simple interfaces provide a powerful services)
- flexible - sercurity
-
odd way interact
fd = open(); pid = fork();
-
-
xv 6
-
RISC-V
-
QEMU
课堂上一些比较有意思的问题
What is unique slash different about saying system calls jump into the kernel, i.e. as opposed to a standard function call that jumps to an function?
The kernel is a piece of code that’s always resident, that has special privileges that were that because it booted the machine booted the kernel, kernel can directly at all kind of hardware, like the disk device that ordinary user programs can’t get at, so if you make an ordinary function call, the function you calling doesn’t get any special privileges with respect to the hardware, whereas if you make a system call into the kernel, that ends up as when it jumps into the kernel, system call implementation in the kernel then gets all these special privileges, so that it can modify all kinds of sensitive and protected hardware resources, like example getting directly at the hard disk.
Do high-level programming languages like python use system calls directly, are there built in slash wrappers for convenience?
A lot of high-level languages are sort of at one of move from system calls, but partially because a lot of languages want to provide portable environment that works on many different operating systems, so they can’t necessary commit to the specific system calls or any one operating system. If you use python, you are somewhat insulated from the system call interface, you know the internally of course python makes, has to make system calls to get its work done. And certainly in python and many other languages, there is usually a way to get directly at the system calls whatever your operating system , you are running on.
char buf[64];
read(0, buf, 64);
What if we set the max read bytes to size of buf to one plus size of buf big, so what if we try to read more than the size?
If there was 65 bytes to read, then the operating system would happily will just copy those 65 bytes to the memory that you provide, and of course there’s something else on the stack up there, maybe the return program counter or an argument or something, and so if you pass 65, then you are inviting a kernel to write junk to an unexpected place in your stack. That’s a bug, and it may cause your program to crash, or do something else unexpected.
How does the complier handles system calls, does assembly generated make a procedure call to some code segment, defined by the operating system?
There’s a special RISC-V instruction, that a program can call that transfer control under the kernel, so indeed when you write C code that makes the system call, like open and write and technically what actually happens is open is a C function in the C library, but the instructions in that function are really machine instructions, it’s not open, the open function that we calling isn’t a C function, implement in assembler and the assembly code consists of this special instructions actually called ecall, on RISC-V, the special instruction that transfer control into the kernel, and then the kernel looks at the processes memory and registers to figure out what the arguments were.
char *argv[] = {"echo", "this", "is", "echo", 0};
exec("echo", argv);
// this is echo
What is the last zero for in argv?
It marks the end of the array, C is so low level that there’s no the C array scheme, doesn’t have a way for code to find out how long the array is.