库文件

先从我们熟悉的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

kernel笔记——库文件与系统调用的更多相关文章

  1. linux库文件编写入门(笔记)

    linux库文件的编写 作者: laomai地址: http://blog.csdn.net/laomai 本文主要参考了如下资料⑴hcj写的"Linux静态/动态链接库的创建和使用&quo ...

  2. makefile笔记10 - makefile 函数库文件

    函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件.在 Unix 下,一般是由命令"ar"来完成打包工作. 一.函数库文件的成员 一个函数库文件由多个文件组成. ...

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

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

  4. 高级C/C++编译技术之读书笔记(四)之定位库文件

    最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...

  5. STM32嵌入式开发学习笔记(二):将功能封装为库文件

    将所有的函数都堆在main.c文件里不是好的选择,庞大的代码文件会是你维护的障碍,明智的做法是,一种功能封装到一个库文件里. 库文件就是你代码开始部分写的#include<xxxx.h>里 ...

  6. 《linux内核设计与实现》读书笔记第五章——系统调用

    第5章 系统调用 操作系统提供接口主要是为了保证系统稳定可靠,避免应用程序恣意妄行. 5.1 与内核通信 系统调用在用户空间进程和硬件设备之间添加了一个中间层. 该层主要作用有三个: 为用户空间提供了 ...

  7. Linux系统学习笔记:文件I/O

    Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...

  8. xv6学习笔记(3):中断处理和系统调用

    xv6学习笔记(3):中断处理和系统调用 1. tvinit函数 这个函数位于main函数内 表明了就是设置idt表 void tvinit(void) { int i; for(i = 0; i & ...

  9. golang调用c++的dll库文件

    最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...

随机推荐

  1. asp.net core 系列 7 Razor框架路由(上)

    一.概述 在上二篇中,主要是介绍了asp.net core mvc中路由的使用,这篇继续介绍路由在ASP.NET Core Razor中的使用.Razor Pages应该使用默认的传统路由,从应用程序 ...

  2. 近期编程总结(i think -1)

    随着“四则运算题”的不断升级,功能实现起来越来越难,需要的知识也越来越多.实现过程中,需要不断地查阅相关资料和与其他人讨论的实现方法. 四则运算2的产生,的确耗费了自己很多的精力,不过反思一下,在不断 ...

  3. Net Configuration Agent

    提出Configuration Agent这样一个东西可能会让人感到奇怪,对于配置信息读取什么还需要一个Agent;那Agent的作用是什么,能达到一个怎样的目的,下面讲解为何需要Agent和其重要性 ...

  4. Java基础12:深入理解Class类和Object类

    更多内容请关注微信公众号[Java技术江湖] 这是一位阿里 Java 工程师的技术小站,作者黄小斜,专注 Java 相关技术:SSM.SpringBoot.MySQL.分布式.中间件.集群.Linux ...

  5. JVM(2)--一文读懂垃圾回收

    与其他语言相比,例如c/c++,我们都知道,java虚拟机对于程序中产生的垃圾,虚拟机是会自动帮我们进行清除管理的,而像c/c++这些语言平台则需要程序员自己手动对内存进行释放.虽然这种自动帮我们回收 ...

  6. Docker折腾手记-安装

    安装 docker红的发紫,所以博主耳闻这么久,也要来折腾折腾了 研究不多,个人目前认为docker给我们带来了以下好处 开发机器因为开发原因,需要配置各种各校的环境,繁琐且耗费资源.配来配去还容易环 ...

  7. 深度学习入门实战(一):像Prisma一样算法生成梵高风格画像

    本文由云+社区发表 作者:董超 导语:现在人工智能是个大热点,而人工智能离不开机器学习,机器学习中深度学习又是比较热门的方向,本系列文章就从实战出发,介绍下如何使用MXnet进行深度学习~ 既然是实战 ...

  8. Django 系列博客(十一)

    Django 系列博客(十一) 前言 本篇博客介绍使用 ORM 来进行多表的操作,当然重点在查询方面. 创建表 实例: 作者模型:一个作者有姓名和年龄. 作者详细模型:把作者的详情放到详情表,包含生日 ...

  9. SpringCloud系列——Eureka 服务注册与发现

    前言 Eureka是一种基于REST(具像状态传输)的服务,主要用于AWS云中定位服务,以实现中间层服务器的负载平衡和故障转移.本文记录一个简单的服务注册与发现实例. GitHub地址:https:/ ...

  10. Scala(三)

    一.控制语句 var x = 40 if(x == 40){ println("greate") } 二.循环 (1) 一般循环 while(a>1){ if(a==2){ ...