Skip to content

Linux中的select函数

最近在排查一个用户同步数据非常慢的问题。使用perf trace -S -p $pid发现,进程的大部分时间花费在了select函数上: 凭直觉觉得有些异常。按照Linux手册上对select的说法: select() allow a program to monitor multiple file descriptors, waiting until one or more of the file descriptors become “ready” for some class of I/O operation (e.g., input possible). A file descriptor is considered…

Read more

一个C文件IO问题

作为练习,我写了下面一个用FILE stream来做读写的C程序, 就是简单的读一个给定的文件,让后将每行打印出来,就像cat命令最简单的用法。

Read more

[转]Monitoring and Tuning the Linux Networking Stack: Receiving Data

最近在网上看到了一篇详细介绍Linux系统上接收网络数据包过程的博客(英文的),觉得很不错,特地分享一下。如果你想做Linux的网络性能优化,这是一篇很好的参考文章。 The networking stack is complex and there is no one size fits all solution. If the performance and health of your networking is critical to you or your business, you will have no choice but to invest a considerable…

Read more

[翻译] 简谈编译、汇编、链接和加载 – part V

W.8 运行时数据结构一个进程就是一个运行着的程序。这意味着操作系统已经把程序的可执行文件加载到内存中,安排好了程序对它的参数和环境变量的访问权限,开始执行它的代码。通常一个进程有5个内存区域,如下表所示: Segment 描述 代码 – text segment 通常称为 text segment, 这里是程序的可执行代码指令区.  比如, 当一个程序同时运行多个实例时,Linux/Unix 会尽可能让他们共享text segment。 这个内存区的内容对应可执行文件的 text section. 初始化的数据 – data segment 非零值的静态分配的数据以及全局数据被加载到data segment.  一个程序有多个进程时,每个进程都有自己的data segment。这个内存区的内容对应可执行文件的 data section. 未初始化数据 – bss segment BSS 表示 ‘Block Started by Symbol’(符号开始的区域)。零值的静态分配的数据以及全局数据被加载到bss segment.  一个程序有多个进程时,每个进程都有自己的bss segment。运行时,bss里面的数据会被放入data segment。在可执行文件中,它们被保存在BSS…

Read more

[翻译] 简谈编译、汇编、链接和加载 – part IV

W. 6: 共享对象的使用方式 要理解一个程序如何使用共享对象,让我们首先检查一下可执行文件的格式以及如何让程序开始运行。 w6.1一些ELF格式的细节 ELF(Executable and Linking Format, 可执行与链接格式)是一个二进制格式,用于SVR4 Unix和Linux系统。它是一种在磁盘上存储程序的格式。ELF不仅简化了创建共享文件的过程,也改进了运行时模块的动态加载。 W6.2 ELF块(sections) Linux及其它使用ELF格式的系统在可执行程序中定义了一些”块“。这些块用于为二进制文件提供指令,并且可被查看。重要的函数块包括GOT(Global Offset Table,全局偏移表),存储系统函数的地址,和PLT(Procedure Linking Table过程连接表),用于存储指向GOT的非直接链接;.init/.fini,用于内部初始化和关闭;.ctors/.dtors,用于constructors and destructors. 数据相关的块有.rodata,用于只读数据,.data用于已经初始化的数据,和.bss,用于未初始化的数据。 下面是一个ELF块的不完全列表(从低到高): .init – Startup .text – String .fini – Shutdown .rodata – Read Only .data – Initialized Data .tdata…

Read more

[翻译] 简谈编译、汇编、链接和加载 – part III

W.3 重定位记录(relocation records) 由于不同的对象文件会互相引用对方的代码和/或数据,所以不同的位置,这些不需要在链接时合并。比如,在下面的图中,包含main()的对象文件含有对funct()和printf()函数的调用。把所有对象文件链接在一起后,链接器使用重定位记录来定位那些需要填充的地址。 W.4 符号表 汇编成机器代码的过程会把代码中所有的标签移除,对象文件格式需要把这些信息存放在不同的地方。符号表就是做这个用的。符号表包含了一个名字及其在text和data块的偏移量的列表。反汇编程序可以把这个过程从对象文件或可执行文件翻译回来。   W.5  链接 链接让分开编译成为可能。如下图所示,一个可执行文件可以由多个可独立编译的源文件编译而来,而且每个文件都可以编译为自己的对象文件。 5.1 共享对象 在一个典型的系统上会有多个程序同时运行。每个程序都依赖于很多函数。而这些函数有很多是标准的C语言的库函数,比如printf(), malloc(), strcpy()等,有些则是非标准的或程序员自定义的函数。 如果每个程序都使用标准的C库(library),那就意味着每个程序都要在它的(地址空间)内部有一份C库。这样就会浪费很多资源,也影响效率和性能。 既然对C库文件的需求是共通的,那么如果每个程序都可以共享访问一份C库文件就是一个更好的选择,而不是每个程序都把标准C库文件加载一份到自己的内存地址中。 这个功能也是在链接过程中来实现的。有些对象是在链接的时候链接进来,而有些则是在程序运行时才链接进来(称为延迟链接或动态链接) 5.2 静态链接 静态链接表示一个程序和它需要的库文件在链接阶段就被链接器合并在一起了。这也意味着这个程序和库文件之间的绑定是固定的,且在程序开始运行之前就是已知的。同时也意味着我们无法改变这个结合状态,除非使用一个新版的库文件重新链接这个程序。 静态链接的程序所用的库(对象)一般是一个以.a为扩展名的文件。一个常见的例子就是标准的C库,libc.a。 如果不确定程序运行时能得到正确的库文件版本,或者想要测试一个新版的库文件,还不想把它作为共享库文件安装,这时可以使用静态链接。 对gcc来说,在编译/链接时使用-static选项会得到静态链接的程序 gcc –static filename.c –o filename 静态编译出的可执行文件会大很多,因为所有需要的信息和文件都要被放入可执行文件中。 5.3 动态链接 动态链接表示程序和它使用的特定库文件并非链接阶段就被链接在一起。相反,链接器在可执行文件中放入特定信息,告诉加载器(loader)代码在哪一个共享对象模块中以及应该使用哪一个运行时链接器来找到这个对象文件并将它与程序绑定。这意味着程序和共享对象之间的绑定是在运行时完成,且在程序开始执行之前。 这种类型的程序称为部分绑定可执行文件,因为它并非全部(符号或引用)可解析的。链接器在链接时间并不会将程序中引用的符号和库文件的特定代码结合起来。相反,链接器只是留一些类似这样的信息:这个程序调用的这个共享对象的这个函数,我只是记一下这个函数在哪个共享对象中。现在我要继续下面的工作。 共享对象中的符号会被验证以确认它们确实存在,但不会被合并到程序中。 链接器在可执行程序中存储了外部库文件的地址,用于找到哪些无法在程序中找到的符号。这造成的实际效果就是把(符号与代码之间的)绑定推迟到了程序运行时。 动态链接程序使用的共享对象通常使用.so的扩展名。一个最常见的例子就是标准C库libc.so。 动态链接的好处有: 1….

Read more
Sidebar