2.2 系统调用的包装函数
系统调用不能被C语言、Python等这种高级编程语言直接发起,只能通过与系统架构紧密相连的汇编语言代码来发起。例如在x86_64架构中,是如下发起getppid()系统调用的。
mov $0x64.%eax
syscall
第1行意思是将getppid的系统调用编号0x6e传递给eax寄存器。这里的系统调用编号是由Linux预先定义好的。第2行,通过syscall命令发起系统调用,切换到内核模式,然后开始执行负责处理getppid的内核代码。
如果没有OS的帮助,写程序的时候就必须根据不同的系统架构为每个系统调用编写相应的汇编语言代码,然后用高级语言调用这些代码发起系统调用,如下。
为了解决这样的问题,OS提供了一系列的系统调用的包装函数,用于系统内部发起系统调用,兼容各种架构。因此,只要使用高级编程语言,调用这些包装函数就可以发起系统调用,如下。
2.3 C标准库
C标准库的定义这里不赘述,Linux也提供了C语言标准库,通常以GNU项目提供的glibc作为C标准库使用,用C语言编写的几乎所以程序都依赖glibc库。glibc还包含了Unix的OS具备各种功能中定义的函数。
Linux提供了ldd用来查看程序所依赖的库。例如:
Alex@ubuntu:~$ ldd /bin/echo
linux-vdso.so.1 (0x00007ffe5d12f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f07f1da7000)
/lib64/ld-linux-x86-64.so.2 (0x00007f07f1fb8000)
Alex@ubuntu:test2_4$ ldd ppidloop
linux-vdso.so.1 (0x00007ffe5d346000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f3bd3ceb000)
/lib64/ld-linux-x86-64.so.2 (0x00007f3bd3ef6000)
可见echo命令也依赖libc库,上一节做实验时我们生成的ppidloop这个程序也依赖libc库。看下Python依赖哪些库。
Alex@ubuntu:~$ ldd /usr/bin/python3
linux-vdso.so.1 (0x00007ffe00de3000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fc55759a000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fc557577000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fc557571000)
libutil.so.1 => /lib/x86_64-linux-gnu/libutil.so.1 (0x00007fc55756c000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fc55741d000)
libexpat.so.1 => /lib/x86_64-linux-gnu/libexpat.so.1 (0x00007fc5573ef000)
libz.so.1 => /lib/x86_64-linux-gnu/libz.so.1 (0x00007fc5573d1000)
/lib64/ld-linux-x86-64.so.2 (0x00007fc5577a0000)
看得出Python也依赖libc库。其实系统上的大部分程序都会依赖到libc,可以自己在电脑上用ldd命令试试看。
2.4 OS提供的程序
OS提供的程序与OS提供的库一样,对绝大多数程序来说是不可或缺的。OS同时还提供了作为自身一部分的、用于更改OS运行方式的程序。
下面列举了一些OS提供的程序。
初始化系统:init
变更系统的运行方式:sysctl、nice、sync
文件操作:touch、mkdir
文本数据处理:grep、sort、uniq
性能测试: sar、iostat
编译: gcc
脚本语言运行环境:perl、python、ruby
shell: bash
视窗系统:X
对于这些程序,其中有些涉及到Linux的基本操作,推荐阅读《鸟哥LINUX私房菜》,一本比较入门的、也比较详细的介绍Linux基本操作的书。