首页 技术 正文
技术 2022年11月10日
0 收藏 812 点赞 4,665 浏览 1890 个字

库文件

先从我们熟悉的c库入手,理解系统调用(system call)。c代码中调用printf函数,经历了以下调用过程:

 

最终输出的功能由内核中write调用完成,c库封装了系统调用。

对于以下hello world程序:

#include
int main()
{
  printf("Hello world.\n");
  return ;
}

我们可以使用ldd查看程序依赖的库文件:

linux # ldd hello
    linux-vdso.so. => (0x00007fff89fe2000)
    libc.so. => /lib64/libc.so. (0x00007fd142094000)
    /lib64/ld-linux-x86-.so. (0x00007fd1423f2000)

输出结果中显示了hello程序依赖的动态库文件,其中linux-vdso.so.1指向进程虚拟内存地址,是一个虚拟的库文件,在每个程序的虚拟内存都存在,其将内核态的调用映射到用户地址空间中,使得调用开销更小。

有些时候,在我们编译程序时,会出现找不到某某lib的提示,又或者ldd查询到某库链接指示”not found”,这是因为ldd在/etc/ld.so.cache中不存在相应库文件的查找路径(使用strace跟踪ldd命令可以看到ld.so.cache文件被读取)。

要解决找不到某库的问题,我们可以将库文件路径加到用户的LIBRARY_PATH环境变量中,也可以添加到全局的/etc/ld.so.conf配置文件中,添加完后以root用户执行ldconfig,以更新/etc/ld.so.cache缓存文件。

使用rpm命令可以查到动态库属于哪个rpm包:

linux # rpm -qf /lib64/libc.so.
glibc-2.11.-0.17.

反过来,对某一rpm包,我们可以查其包含的内容:

linux # rpm -ql glibc-2.11.-0.17.
/etc/bindresvport.blacklist
/etc/default/nss
/etc/gai.conf
/etc/ld.so.cache
/etc/ld.so.conf
……

devel包中包含了c库函数的头文件,而普通包中不包含头文件,可以使用rpm查询对比开发包和普通包:

rpm -ql glibc-2.4-31.77.88.4
rpm -ql glibc-devel-2.4-31.77.88.4

系统调用

每一个系统调用对应一个系统调用号(system call number),使用系统调用的过程就是将系统调用号和参数传递给内核。

使用objdump,可以对库文件进行反汇编,以下对/lib64/libc.so.6进行反汇编,并查看getpid函数相应的部分汇编代码:

00000000000933e0 <__getpid>:
……
933fa:
933fb: c0 test %eax,%eax
933fd: f0 jne 933ef <__getpid+0xf>
933ff: b8 mov $0x27,%eax
: 0f syscall
: d2 test %edx,%edx
……

在以上输出中,mov指令将系统调用号0x27放入eax寄存器中,0x27作为syscall的参数,syscall完成调用getpid的工作。

系统调用与系统调用号对应关系在include/asm/unistd.h中定义,我们可以查到getpid相应的定义语句:

#define __NR_getpid 39
__SYSCALL(__NR_getpid, sys_getpid)

unistd.h定义了POSIX标准提供的系统调用,所有符合POSIX标准的Unix系统均提供该头文件。

我们可以直接传递系统调用号给syscall函数,完成系统调用,以下程序说明了如何使用syscall直接完成getpid系统调用:

#define _GNU_SOURCE
#include
#include
#include
#include
int main(int argc, char *argv[])
{
pid_t tid;
tid = syscall(SYS_gettid);
printf("%d\n", tid);
}

因而总结来说,使用系统调用的方式有两种:

  1. c库中封装了系统调用,通过c库间接调用
  2. 传递系统调用号,通过syscall直接调用

第2种方式存在的意义在于,当kernel提供了新的系统调用,而c库又没有更新时,可以使用syscall调用新的系统调用。

Reference: Chapter 5 – System Calls, Linux kernel development.3rd.Edition

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,487
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,903
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,736
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,486
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:8,126
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:5,289