home archives github knives links
tags
categories 操作系统
only title title and content
os复习
2019-06-21

编译 链接

gcc -o的系统调用

elf文件格式

终端 shell

为什么按键能显示在屏幕上?按下回车命令就会执行?

I/O设备模型

$ ps
PID TTY TIME CMD
6577 pts/3 00:00:00 zsh
9178 pts/3 00:00:00 ps

$ ps -l
F S UID PID PPID C PRI NI ADDR SZ WCHAN TTY TIME CMD
0 S 1000 6577 1883 0 80 0 - 7676 sigsus pts/3 00:00:00 zsh
4 R 1000 9265 6577 0 80 0 - 7531 - pts/3 00:00:00 ps

./hello如何被执行

  1. 先调用fork
  2. 子进程调用execve->hello
  3. 父进程wait
$ sudo echo "a" > shit
zsh: 权限不够: shit # 重定向发生在`execve`之前,open失败

$ sudo bash -c 'echo "a" > shit'

加载器(文件如何变成进程?)

第一条指令在哪里?

main函数执行之前,系统发生了什么?

gdb shit

(gdb) starti
Program stopped.
0x00007ffff7fd4090 in _start () from /lib64/ld-linux-x86-64.so.2
# 不是hello的_start,是加载器的_start(静态链接)(动态加载在操作系统的...)

(gdb) info inferior # 查看进程号
* 1 process 6569 /shit

$ pmap 6569
6569: /shit
0000555555554000 4K r---- shit # 代码和数据
0000555555555000 4K r-x-- shit
0000555555556000 4K r---- shit
0000555555557000 8K rw--- shit
00007ffff7fce000 12K r---- [ anon ]
00007ffff7fd1000 8K r-x-- [ anon ]
00007ffff7fd3000 4K r---- ld-2.28.so
00007ffff7fd4000 128K r-x-- ld-2.28.so
00007ffff7ff4000 32K r---- ld-2.28.so
00007ffff7ffc000 8K rw--- ld-2.28.so
00007ffff7ffe000 4K rw--- [ anon ]
00007ffffffde000 132K rw--- [ stack ]
ffffffffff600000 4K r-x-- [ anon ]
total 352K

(gdb) b _start
Breakpoint 1 at 0x555555555060

(gdb) c
Breakpoint 1, 0x0000555555555060 in _start ()

$ pmap 6569
6569: /shit
0000555555554000 4K r---- shit
0000555555555000 4K r-x-- shit
0000555555556000 4K r---- shit
0000555555557000 4K r---- shit
0000555555558000 4K rw--- shit
00007ffff7dc3000 136K r---- libc-2.28.so # printf的代码
00007ffff7de5000 1476K r-x-- libc-2.28.so
00007ffff7f56000 304K r---- libc-2.28.so
00007ffff7fa2000 4K ----- libc-2.28.so
00007ffff7fa3000 16K r---- libc-2.28.so
00007ffff7fa7000 8K rw--- libc-2.28.so
00007ffff7fa9000 24K rw--- [ anon ]
00007ffff7fce000 12K r---- [ anon ]
00007ffff7fd1000 8K r-x-- [ anon ]
00007ffff7fd3000 4K r---- ld-2.28.so
00007ffff7fd4000 128K r-x-- ld-2.28.so
00007ffff7ff4000 32K r---- ld-2.28.so
00007ffff7ffc000 4K r---- ld-2.28.so
00007ffff7ffd000 4K rw--- ld-2.28.so
00007ffff7ffe000 4K rw--- [ anon ]
00007ffffffde000 132K rw--- [ stack ]
ffffffffff600000 4K r-x-- [ anon ]
total 2320K

...
Breakpoint 1, 0x0000555555555149 in main ()

$ pmap 6569
# 输出同上

printf

printf代码位于何处?

static void __attribute__ ((constructor)) fuck()// 在main之前执行
{
printf("hello\n");// 编译优化,puts
}

实现线程安全的printf?(20分的并发编程题)

PV操作

生产者消费者问题

void producer() 
{
while (1) {
mutex_lock(&mutex);

if (count == n) wait(&notfull, &mutex);
produce();
count ++;
signal(&notempty);

mutex_unlock(&mutex);
}
}

void consumer()
{
while (1) {
mutex_lock(&mutex);

if (count == 0) wait(&notempty, &mutex);
consume();
count --;
signal(&notfull);

mutex_unlock(&mutex);
}
}
void producer()
{
while (1) {
P(&space);
mutex_lock(&mutex);

produce();

mutex_unlock(&mutex);
V(&items);
}
}

void consumer()
{
while (1) {
P(&items);
mutex_lock(&mutex);

consume();

mutex_unlock(&mutex);
V(&space);
}
}

printf末尾换行

异常退出

int main()
{
FILE *fp = fopen("del", "w");
setbuf(fp, NULL); // 自定义fp的缓冲区,NULL:不要缓冲区
fputs("fuck", fp);
assert(0);// 程序异常退出
return 0;
}
# cont'd
$ gcc hello.c -o shit
$ ./shit
shit: hello.c:11: main: Assertion `0' failed.

$ cat del
fuck%

fork

int main()
{
for (int i = 0; i < n; i ++) {
fork();
printf("hello\n");
}
return 0;
}
n ./hello │ wc -l ./hello
1 2 2
2 8 6
int main()
{
setbuf(stdout, NULL);
for (int i = 0; i < n; i ++) {
fork();
printf("hello\n");
}
return 0;
}
n ./hello │ wc -l ./hello
1 2 2
2 6 6

printf的系统调用

write

write写到哪里?

文件系统如何实现?

FAT(文件分配表)

FAT32文件系统快速入门,CSDN
长文件名

ext2(inode)

鸟哥的Linux私房菜:Linux的ext2档案系统

如何保护我们的数据不受损害?

RAID

鸟哥的Linux私房菜:Software RAID

RAID 容量 容错 顺序度 随机读 顺序写 随机写
0 $n$ 0 $n$ $n$ $n$ $n$
1 $n/2$ $> n/2$ $n$ $n/2$ $n/2$
4 $n-1$ 1 $n-1$ $n-1$ $n-1$ $1/2$
5 $n-1$ 1 $n-1$ $n$ $n-1$ $n/4$

fsck

扫描inodes里的所有数据块,检查bitmap的一致性

日志

鸟哥的Linux私房菜:Linux的ext2档案系统

在磁盘上保存所有对数据结构的操作,每次启动时重做这些操作,在内存里重新建立文件系统

优化