库文件

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

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

对于以下hello world程序:

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

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

linux # ldd hellolinux-vdso.so.1 => (0x00007fff89fe2000)libc.so.6 => /lib64/libc.so.6 (0x00007fd142094000)/lib64/ld-linux-x86-64.so.2 (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.6
glibc-2.11.1-0.17.4

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

linux # rpm -ql glibc-2.11.1-0.17.4
/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: 00
933fb: 85 c0           test %eax,%eax
933fd: 75 f0           jne 933ef <__getpid+0xf>
933ff: b8 27 00 00 00  mov $0x27,%eax
93404: 0f 05           syscall
93406: 85 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

kernel笔记——库文件与系统调用相关推荐

  1. 报错笔记:打开软件出现您缺少mfco42d.dll和msvcrtd.dl库文件

    报错环境:自己在写工具的时候,自己可以用,正常打开,但将软件拷贝到其他人的电脑中后,就会出现打开 软件出现您缺少mfco42d.dll和msvcrtd.dl库文件的错误. 按照百度说法,下载mfco4 ...

  2. python学习笔记(自定义库文件路径)

    博主最近在弄接口自动化.主要是基于python自带的unittest框架.包括 Pubilc模块定义所有接口. Main模块根据业务需求重新封装接口便于测试. config文件导入测试业务的固定参数. ...

  3. 野火STM32学习笔记一、固件库文件分析

    STM32固件库文件分析 汇编编写的启动文件 startup_stm32f10x_hd.s: 设置堆栈指针.设置PC指针.初始化中断向量表.配置系统时钟.调用C库函数main最终去到C的世界 时钟配置 ...

  4. SRE运维工程师笔记-Linux文件管理和IO重定向

    SRE运维工程师笔记-Linux文件管理和IO重定向 1. 文件系统目录结构 1.1 文件系统的目录结构 1.2 常见的文件系统目录功能 1.3 应用程序的组成部分 1.4 CentOS 7 以后版本 ...

  5. automake生成静态库文件_动手 | 奶奶级的动态库入门

    程序编译过程 库文件 静态链接和动态链接的区别? 从0开始 - 创建和使用静态链接库 创建静态库项目 向静态库中添加文件 编译静态库 创建引用静态库的C++控制台应用 在应用中使用静态库功能 从0开始 ...

  6. Linux下gcc编译中关于头文件与库文件搜索路径相关问题

    如何指定GCC的默认头文件路径 网上偶搜得之,以之为宝:) 原地址:http://blog.chinaunix.net/u/28781/showart.php?id=401631 ========== ...

  7. .h头文件 .lib库文件 .dll动态链接库文件关系

    .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和lib就够 ...

  8. .h头文件 .lib库文件 .dll动态库文件之间的关系

     .h头文件是编译时必须的,lib是链接时需要的,dll是运行时需要的. 附加依赖项的是.lib不是.dll,若生成了DLL,则肯定也生成 LIB文件.如果要完成源代码的编译和链接,有头文件和li ...

  9. Qt下使用vs编译的库文件

    Qt下调用VS制作的静态库    1.制作静态库的编译器和Qt版本的编译器是一样     如果是使用Visual Studio 制作的静态库,比如使用Visual Studio 2013制作的,而要使 ...

最新文章

  1. Single-Shot Calibration:基于全景基础设施的多相机和多激光雷达之间的外参标定(IROS2021)...
  2. 数组去重--这几种方法够不?
  3. MySQL复制性能优化
  4. 坐地铁的好心MM们小心啊,周末刚经历了一个地铁新骗术
  5. java 多线程工具_多线程测试工具groboutils的使用
  6. 视觉检测无脊椎机器人或vipir_深入浅出人工智能前沿技术—机器视觉检测,看清人类智慧工业...
  7. 【cv2】:关于opencv-Python的函数
  8. 无线充qi协议c语言详解,QI无线充通信协议数据包格式解析
  9. comsol移动网格_COMSOL动网格调试
  10. jmu-ds-集合的并交差运算
  11. 【转】如何检测wifi信号强度? -- 不错
  12. 解决“c#:未将对象引用设置到对象的实例”
  13. synergy安装和使用小结
  14. HTTP服务器的实现--CGI中POST表单。
  15. 数据库课程设计-图书馆管理系统(1.数据库分析部分)
  16. tensorflow零基础入门学习
  17. 易优cms compare 比较标签使用方法
  18. Windows Server AD域控服务器升级/迁移(AD域控的五大角色转移)
  19. 最全Java成神学习路线总结!!!
  20. linux zip 包解压失败

热门文章

  1. [Java] 蓝桥杯ALGO-98 算法训练 数位分离
  2. 【C++】n_element的用法
  3. 网络七层协议_IT人计算机网络浅析
  4. 跟随我在oracle学习php(27)
  5. x/(x+1)=ln(x+1)=x
  6. 分解模式 - 按业务领域分解模式划分微服务
  7. python基础===字符串的制表,换行基础操作
  8. Go语言栈定义及相关方法实现
  9. leetcode5 Longest Palindromic Substring 最长且为回数的子字符串
  10. util:properties/加载的配置文件中有中文导致乱码,如何通过分析源码解决问题?...