extreme-c-learning-notes ch10
ls
, mkdir
, ifconfig
, ps
, kill
等等。ls -l | grep a.out
。硬件(Hardware): 众所周知,操作系统的主要任务是允许用户与硬件进行交互并使用它们。
内核(Kernel): 内核是操作系统中最重要的部分。因为他是最靠近硬件的层,相当于一个包装器,向其他层提供所连接硬件的功能。由于内核层可以直接访问硬件,它拥有系统中所有可用资源的最高使用权限。内核层具有无限访问硬件的权限,其他层不具备这种无限访问权限。事实上,是将内核空间(kernel space) 和用户空间(user space) 分开。
Shell层: Shell 层有许多小程序组成,它们共同构成一组工具,使得用户或应用程序可以使用内核服务。它还包含一组用 C 语言编写的库,程序员可以使用这些库为 Unix 编写新的应用程序。
用户应用程序(User Applications): 包括了所有应用在 Unix 系统上的实际应用程序,例如数据库服务、web服务、邮件服务、web浏览器、工作表程序和文本编辑程序,等等。
我们知道,系统调用(system calls,或英文简写为 syscalls) 是由 libc 实现中的代码触发的。事实上,这就是触发内核例程的方式,在 SUS 中,以及在兼容 POSIX 的系统中,有一个程序用于在程序运行时跟踪系统调用。
ExtremeC_examples_chapter10_1.c
#include
int main(int argc, char **argv)
{
sleep(1);
return 0;
}
在 Linux 系统中使用 strace 监视上述例程
$ cc ExtremeC_examples_chapter10_1.c -lc -o ex10_1.out
$ strace -o ex10_1.log ./ex10_1.out
Shell 窗口显示了 Linux 中使用 strace 监视上述例子调用的系统调用的输出 ex10_1.log;从输出的log中可以看到,该例程发起了许多系统调用,其中一些时关键加载共享目标库的,特别是在初始化进程时。
openat(AT_FDCWD, "/lib/x86_64-linux-gnu/libc.so.6", O_RDONLY|O_CLOEXEC) = 3
上述系统调用打开 libc.so.6
共享目标库文件。这个共享目标库包含了 Linux 的 libc 的实际实现。
clock_nanosleep(CLOCK_REALTIME, 0, {tv_sec=1, tv_nsec=0}, 0x7ffed1588c00) = 0
可以看出程序调用了 clock_nanosleep
系统调用。传递给这个系统调用的值 tv_sec=1, tv_nsec=0
也就是 1 秒。
系统调用类似于函数调用,请注意每个系统调用都有一个专用的、预先设定的常量,还有一个特定的名称和一个参数列表。每个系统调用执行一个特定的任务。在本例中 clock_nanosleep
让调用线程休眠指定的秒数。关于系统调用的更多信息可以查阅 Linux Programmer’s Manual;
$ man clock_nanosleep
从 Linux Programmer’s Manual 手册中可以看出:
clock_nanosleep
是一个系统调用- 可以在 shell 层调用
time.h
中定义的clock_nanosleep
和nanosleep
函数来访问系统调用。注意,我们使用了unitsd.h
里的
sleep
函数。我们也可以使用前面time.h
里的两个函数。值得注意的是,两个头文件和前面的所有函数,以及实际使用的函数,都是 SUS 和 POSIX 的一部分。
使用 FreeBSD 的源码,查看 libc 中实际系统调用的位置
$ git clone https://github.com/freebsd/freebsd-src.git
...
$ cd freebsd-src-main/lib/libc
$ grep sys_nanosleep . -R
./include/libc_private.h:int __sys_nanosleep(const struct timespec *, struct timespec *);
./sys/Symbol.map: __sys_nanosleep;
./sys/interposing_table.c: SLOT(nanosleep, __sys_nanosleep),
./sys/nanosleep.c:__weak_reference(__sys_nanosleep, __nanosleep);
在 ./sys/interposing_table.c
文件中可以看到,nanosleep
函数被映射到了 __sys_nanosleep
函数中。因此,任何对 nanosleep
函数的调用都会导致 __sys_nanosleep
被调用。
grep clock_nanosleep . -R
/include/un-namespace.h:#undef clock_nanosleep
./include/libc_private.h: INTERPOS_clock_nanosleep,
./include/libc_private.h:int __sys_clock_nanosleep(__clockid_t, int,
./include/namespace.h:#define clock_nanosleep _clock_nanosleep
./tests/sys/Makefile:NETBSD_ATF_TESTS_C+= clock_nanosleep_test
./sys/clock_nanosleep.c:__weak_reference(__sys_clock_nanosleep, __clock_nanosleep);
./sys/clock_nanosleep.c:#pragma weak clock_nanosleep
./sys/clock_nanosleep.c:clock_nanosleep(clockid_t clock_id, int flags, const struct timespec *rqtp,
./sys/clock_nanosleep.c: __libc_interposing[INTERPOS_clock_nanosleep])(clock_id, flags,
./sys/Symbol.map: clock_nanosleep;
./sys/Symbol.map: __sys_clock_nanosleep;
./sys/interposing_table.c: SLOT(clock_nanosleep, __sys_clock_nanosleep),
./sys/Makefile.inc: clock_nanosleep \
./sys/Makefile.inc:MLINKS+=nanosleep.2 clock_nanosleep.2
...
同样在 ./sys/interposing_table.c
文件中可以看到,clock_nanosleep
函数被映射到了 __sys_clock_nanosleep
函数中。因此,任何对 clock_nanosleep
函数的调用都会导致 __sys_clock_nanosleep
被调用。
以 _sys
开始的函数是 FreeBSD 约定的实际系统调用函数。请注意,这是 libc
实现的一部分,使用的命名约定和其它与实现相关的配置都是特定于 FreeBSD 的。
内核层的主要目的是管理系统中的硬件,并以系统调用的方式公开硬件提供的功能。
内核是一个进程,像我们知道的任何其他进程一样,它执行一系列指令。但是内核进程(kernel process) 与普通进程有本质上的不同,普通进程就是我们所知道的用户进程(user process) 。
exec
或 fork
系统调用创建的。大多数 Unix 系统都具备这些系统调用。Tips:
操作系统运行时有两种不同的工作状态。其中一个专用于内核进程,被称为内核域(kernel land)或内核空间(kernel space);另一个专用于用户进程,被称为用户域(user land)或用户空间(user space)。通过用户进程调用系统调用将这两个域结合在一起。
一个典型的 Unix 内核的内部结构可以通过内核执行的任务来识别。事实上,管理硬件并不是内核执行的唯一任务。下面列出了 Unix 内核的职能。
/dev
存放映射的设备文件。所有连接的硬盘驱动器、网络适配器、USB设备等都映射为 /dev
路径下的文件。用户进程可以使用这些设备文件与设备通信。Unix 架构下不同层的内部结构
Unix 内核完全隐藏了 CPU 和物理内存,它们由内核直接管理,不允许从用户空间进行访问。Unix 内核中的内存管理(Memory Management) 和调度器(Scheduler) 单元分别负责管理物理内存和 CPU。但对于连接到 Unix 系统的其它外围设备,情况是不同的。它们通过一种称为设备文件(device file)的机制公开。可以在 Unix 系统的 /dev
路径中看到这些文件。
以下是可以在普通 Linux 机器上找到的设备文件列表:
$ls -l /dev
total 0
crw-r--r-- 1 root root 10, 235 Feb 3 14:33 autofs
drwxr-xr-x 2 root root 40 Feb 3 14:33 block
drwxr-xr-x 2 root root 100 Feb 3 14:33 bsg
...
可以看到,相当多的设备连接到机器上。当然,并非所有的设备都是真实的硬件。Unix 中对硬件设备的抽象使它能够拥有虚拟设备(virtual devices)。