kernel笔记——库文件与系统调用
库文件
先从我们熟悉的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);
}
因而总结来说,使用系统调用的方式有两种:
- c库中封装了系统调用,通过c库间接调用
- 传递系统调用号,通过syscall直接调用
第2种方式存在的意义在于,当kernel提供了新的系统调用,而c库又没有更新时,可以使用syscall调用新的系统调用。
Reference: Chapter 5 - System Calls, Linux kernel development.3rd.Edition
kernel笔记——库文件与系统调用的更多相关文章
- linux库文件编写入门(笔记)
linux库文件的编写 作者: laomai地址: http://blog.csdn.net/laomai 本文主要参考了如下资料⑴hcj写的"Linux静态/动态链接库的创建和使用&quo ...
- makefile笔记10 - makefile 函数库文件
函数库文件也就是对 Object 文件(程序编译的中间文件)的打包文件.在 Unix 下,一般是由命令"ar"来完成打包工作. 一.函数库文件的成员 一个函数库文件由多个文件组成. ...
- python学习笔记(自定义库文件路径)
博主最近在弄接口自动化.主要是基于python自带的unittest框架.包括 Pubilc模块定义所有接口. Main模块根据业务需求重新封装接口便于测试. config文件导入测试业务的固定参数. ...
- 高级C/C++编译技术之读书笔记(四)之定位库文件
最近有幸阅读了<高级C/C++编译技术>深受启发,该书深入浅出地讲解了构建过程(编译.链接)中的各种细节,从多个角度展示了程序与库文件或代码的集成方法,提出了面向代码复用和系统集成的软件架 ...
- STM32嵌入式开发学习笔记(二):将功能封装为库文件
将所有的函数都堆在main.c文件里不是好的选择,庞大的代码文件会是你维护的障碍,明智的做法是,一种功能封装到一个库文件里. 库文件就是你代码开始部分写的#include<xxxx.h>里 ...
- 《linux内核设计与实现》读书笔记第五章——系统调用
第5章 系统调用 操作系统提供接口主要是为了保证系统稳定可靠,避免应用程序恣意妄行. 5.1 与内核通信 系统调用在用户空间进程和硬件设备之间添加了一个中间层. 该层主要作用有三个: 为用户空间提供了 ...
- Linux系统学习笔记:文件I/O
Linux支持C语言中的标准I/O函数,同时它还提供了一套SUS标准的I/O库函数.和标准I/O不同,UNIX的I/O函数是不带缓冲的,即每个读写都调用内核中的一个系统调用.本篇总结UNIX的I/O并 ...
- xv6学习笔记(3):中断处理和系统调用
xv6学习笔记(3):中断处理和系统调用 1. tvinit函数 这个函数位于main函数内 表明了就是设置idt表 void tvinit(void) { int i; for(i = 0; i & ...
- golang调用c++的dll库文件
最近使用golang调用c++的dll库文件,简单了解了一下,特作此笔记:一.DLL 的编制与具体的编程语言及编译器无关 dll分com的dll和动态dll,Com组件dll:不管是何种语言写的都可以 ...
随机推荐
- C++版 - 剑指offer之面试题37:两个链表的第一个公共结点[LeetCode 160] 解题报告
剑指offer之面试题37 两个链表的第一个公共结点 提交网址: http://www.nowcoder.com/practice/6ab1d9a29e88450685099d45c9e31e46?t ...
- IntelliJ IDEA maven项目new里没有package
idea maven项目new里没有package. 如图,idea maven项目new里没有package.: 这是因为java是普通的文件夹,要设置为Source Root 设置好以后可以了.
- 如何理解git checkout -- file和git reset HEAD -- file
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/001374831943254ee ...
- AppBoxFuture(二): Say goodbye to sql!
信息管理类应用系统离不开关系数据存储,目前大家基本都使用的是传统的数据库如MySql.Postgres等.作者从事信息化建设十多年,个人认为传统的数据库存在以下的问题: 扩展问题: 系统数据的 ...
- Service Worker MDN英文笔记
前言: 以前学习基础知识的时候总看别人写的入门文章,但有时候还是一脸懵逼,直到自己用心阅读了MDN的英文文档才对基础知识的一些理论有了更深的理解,所以我在边阅读文档的时候边记录下帮助比较大的,也方便大 ...
- ROS笔记2 构建一个package
构建package catkin_make 可以理解为一个集成了CMake和make的命令行工具 通常的cmake构建如下 # In a CMake project $ mkdir build $ c ...
- golang判断文件是否存在
判断一个文件是否存在是一个相当常见的需求,在golang中也有多种方案实现这一功能. 现在我们介绍其中两种最常用也是最简单的实现,第一种将是跨平台通用的,而第二种则在POSIX平台上通用. 跨平台实现 ...
- 修复UEFI模式下Manjaro Linux启动问题
上周在更新Manjaro Linux的时候误触了电源键,导致内核更新了一半系统强制关机,重启时正常进入grub但无法正常引导进入系统. 由于不想重装系统(一大堆环境和工具的配置还是相当繁琐的),加上初 ...
- PhpStorm 安装ApiDebugger
ApiDebugger,是一个开源的接口调试IntelliJ IDEA插件,具有与IDEA一致的界面,无需切换程序即可完成网络API请求,让你的code更加沉浸式. 安装 File->Setti ...
- rocketmq 发送时异常:system busy 和 broker busy 解决方案
记一次 rocketmq 使用时的异常. 这里就不说什么rocketmq 源码啥的了,因为没看过.网上一搜这两个异常 大部分都是什么源码解读,也没说出现后的解决办法(蓝瘦香菇). 大量测试发现: 1. ...