Introduction

程序员的自我修养——链接、装载与库

Last step before my entering to OS kernel

第一次有想写一本这样的书的念头是在2006年底,当时我正在念研一,想起未来还有一年多漫长而又相对空闲的研究生生涯,觉得写一本这样的书大概是比较好的“消遣活动”。

我始终坚持认为作为开发者,MOP(Market/Money Oriented Programming)才是唯一不变的编程范式。

Part 1 温故而知新

Any problem in computer science can be solved by another layer of indirection.

By David Wheeler (Attributed in: Butler Lampson. Principles for Computer System Design. Turing Award Lecture. February 17, 1993.)

run time lib

Between kernel and applications, there is a runtime library serving as OS API

1
2
3
4
$ file a.out
a.out: ELF 64-bit LSB shared object # Application
dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2 # rt
for GNU/Linux 3.2.0 # OS

Under this circumstance, the run time library here is glibc

Memory sharing

segment

Using segment strategy, the programs do not need relocation, the OS(or hardware, like MMU) provide a mapping function each time

1
2
3
; content of A, accessing memory 0x00000001
mov 0x00000001,%eax
mov (%eax), %ebx
1
2
3
4
5
6
7
8
$ ./a.out # first instant of A
# allocate memory 0x00100000~0x00B00000 to A
# mapping function f = lambda va : va + 0x00100000
# When A access [0x00000001], acutally it is accessing [0x00100001]
$ ./a.out # another instant of A
# allocate memory 0x34100000~0x34b00000
# mapping function f = lambda va : va + 0x34100000
# When A access [0x00000001], acutally it is accessing [0x34100001]

Threading

Windows对进程和线程的实现如同教科书一般标准,Windows内核有明确的进程和线程概念

Linux内核中并不存在真正意义上的线程概念,Linux将所以执行实体(both process and thread)都当作任务(task),每个任务都类似一个单线程的进程。

Linux下不同任务之间可以选择共享内存空间,因而在实际意义上共享了一个内存空间的任务构成了一个进程,这些任务也就成了进程中的线程

1
2
3
int clone(int (*fn)(void *), void *child_stack,
int flags, void *arg, ...
/* pid_t *ptid, void *newtls, pid_t *ctid */ );
Difference between semaphore and mutex lock

semaphore is shared across all the threads, mutex lock is unique to the owner

信号量在整个系统可以被任意线程获取并释放。而互斥量则要求哪个线程获取了互斥量,哪个线程就要负责释放这个锁,其他线程去释放该互斥量是无效的

Threading safety

即使可以用lock阻止内存共享的安全问题,CPU指令乱序执行仍然会造成问题

barrier指令可以阻止CPU将该指令之前的指令交换到barrier之后

https://stackoverflow.com/questions/19965076/gcc-memory-barrier-sync-synchronize-vs-asm-volatile-memory

MoreAboutC

Notes for C 语言编程透视

Format your C code

1
2
$ indent -kr file.c # format C source code according to K&R format
$ man indent # more style

Before

1
2
3
4
5
6
7
8
9
10
11
12
#include <stdio.h>
#include <dirent.h>
int main(){
FILE * fp = fopen("/root/.cache/test/mountpoint/file1","r");
char line [1000];
while( fgets(line, 1000, fp) ){ puts(line); }

DIR * dp = opendir("/root/.cache/test/mountpoint/mydir");
struct dirent * entry ;
while( (entry = readdir(dp)) != NULL ){ puts(entry->d_name); }

}

After

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
#include <stdio.h>
#include <dirent.h>
int main()
{
FILE *fp = fopen("/root/.cache/test/mountpoint/file1", "r");
char line[1000];
while (fgets(line, 1000, fp)) {
puts(line);
}

DIR *dp = opendir("/root/.cache/test/mountpoint/mydir");
struct dirent *entry;
while ((entry = readdir(dp)) != NULL) {
puts(entry->d_name);
}

}