关闭
当前搜索:

小练习 - 单链表冒泡排序,交换指针域

链表的排序,好的做法是交换指针域。链表节点的数据域可能比较大,交换数据域可能会涉及拷贝过多的内存,影响性能。链表是链式存储,无法随机访问(base_addr + offset), 所以比较适合的办法是用比较两两相邻节点的冒泡排序法。当然还有一个办法就是,把所有的链表地址存到一个数组里,排序后重新遍历设置所有指针域,这个就多了两次遍历,也可以。下面是交换指针域的一个单链表冒泡排序的例子: #inc......
阅读(25) 评论(0)

Linux C用variadic macro可变参数宏封装日志接口

在实际的项目中,一般日志接口可以打印出对应的时间、行号、函数名、模块名、级别等信息,可以用variadic macro可变参数进行简单的封装。一个例子: #include <stdio.h> #include <sys/time.h> #include <time.h> /* 日志开关 */ #define LOG_SWITCH 1 /* 获取时间戳 ......
阅读(52) 评论(0)

Linux C variadic可变参数:va_list 在x86和x64下的区别与实现原理

仔细研究了下va_list的实现原理。通过看对应的汇编代码实现和Intel ABI手册,发现: 在x86平台下,va_list可变传参是通过栈来进行; 在x64平台下,va_list可变传参是是默认的calling convention; 这是Inter官方的Linux ABI文档,详细说明了可变参的底层实现,以及相关的使用约定。 The va_list type is an ar......
阅读(48) 评论(0)

Linux C编译和使用so共享库

本文给出一个Linux C 编译和使用共享库so的一个小例子。如下: 文件 my_math.c // @file: my_math.c #include "my_math.h" int add(int a, int b) { return a + b; } // @file: my_math.h int add(int a, int b); 文件 test.c // @f......
阅读(98) 评论(0)

Linux C/C++ 程序员毕业工作两年多来的感想

从2015年年中毕业到现在2017年年底,自己已经工作两年半了。总结一下自己工作两年多的感想。主要是三点: 1. 学习的方法与态度 2.技术与业务的平衡 3. 技术之外的学习...
阅读(369) 评论(0)

Linux 文件描述符解析

关键数据结构在现代操作系统抽象中,进程是资源管理的最小单位,线程是CPU调度的最小单位。Linux有着“一切皆文件”的说法,很大的原因就是文件描述符这个强大的抽象,为I/O操作提供了一个统一的数据结构和接口。内核维护的3个数据结构: 进程级的文件描述符表(descriptor table),每个进程都有自己独立的文件描述符表,主要包含了是:控制标志(flags)和指向打开文件表象的指针。POSIX标...
阅读(178) 评论(0)

Linux C语言函数入参和返回值是结构体时的汇编分析

在C语言程序中,一般不会直接传一个结构体给一个函数,也不会让函数的返回值直接返回一个结构体,这样会拷贝过多影响效率。但是这样也是合法的,有时候也会使用,并且有时候效率也并不会变得太差。 C函数传参:参数少或者传入的结构体小只借助寄存器即可,否则借助栈。 C函数返回值:如果返回一个比较小的结构体,借助寄存器即可,否则依旧借助栈。按调用约定,当返回值是较大的结构体时,会在caller栈里产生一个临......
阅读(774) 评论(0)

Linux C程序函数调用栈帧结构

Linux C程序的反汇编,每个函数第一个指令都是push %rbp,即当caller者调callee时,指令callq <fun addr> callee返回后的下一个指令地址压入栈帧,然后push %rbp 保存 rbp寄存器,紧接着mov %rsp,%rbp 更新rbp 寄存器这样层层调用构成函数调用栈,每个栈帧开始就是存的上一个栈帧的rbp, 结尾就是调用callee后的下一个......
阅读(471) 评论(0)

AWK 常见基本用法

在Linux下进行一些简单的文本处理, 尤其是涉及数据基本过滤加工汇总的,awk 是十分方便的, 复杂的处理还是用python比较好。总结一下一些 awk 的常用技巧:按列条件过滤awk '{print $1, $3}' info.txt # 输出指定列 awk '$2==1 && $5=="ERROR"' info.txt # 按条件过滤,$2、$5是内置变量,表指定的列,...
阅读(300) 评论(0)

规律的作息

作息是否规律对一个人的身体状态影响很大。前阵子看了哈佛幸福课,知道自制力是一个有限的资源,好的做法的就是一段时间集中养成一个好习惯,然后保持下来。自己也算培养两个了:(1)定期的锻炼;(2)晚上或多或少的学习点东西。下一个自己要集中培养的习惯就是规律断点作息。因为要上班,自己早晨起床的时间通常也是比较固定的,但是晚上睡觉却不是很规律了。经常时不时就睡的比较晚,而且大部分都不是因为工作原因,都是晚上自...
阅读(363) 评论(1)

操作系统原理:动态内存分配

用户层malloc的实现malloc的底层调用sbrk和mmapmalloc是C语言标准库函数,是在用户层实现的。在Linux里,malloc编译好,是在run-time的动态库so中,通过标准库头文件把api声明给调用者。malloc、realloc和free是C语言的用户层的标准库函数,底层调用的是mmap和sbrk函数。大致如下图: malloc 底层调用的 sbrk 和 mmap. 申...
阅读(1442) 评论(0)

小练习 - 哈希表之分离链接法

小练习 - 哈希表之分离链接法哈希表十分常用,这里做个小练习,冲突解决使用分离链接发。从哈希表的C语言实现角度来看,Hash本质上做了这样一个映射:key -> hashtable[index] -> addr, 新插入一个数据时,key由数据本身决定,存储地址addr则是系统分配,key通过哈希函数可以算出索引,查找索引对应哈表项目得到地址。采用分离链接法,底层数据结构主要是数据和单链表。这里未考...
阅读(312) 评论(0)

小练习 - IP地址int与string相互转换C实现

有次用到了IP地址与str的转换,不想用socket的库函数,发现网上很多实现都挺啰嗦的,自己实现一个记录下。/* ip 字符串合法性由调用者保证 */ unsigned int ip_str2int(const char* ip) { unsigned int re = 0; unsigned char tmp = 0; while (1) { if (*i...
阅读(933) 评论(0)

小练习 - 基于链表的栈和队列

随手练下基本的数据结构,基于链表实现一个动态大小的栈和队列,最基本简单的数据结构要注意各种边界场景。基于链表实现,频繁增删调用mallc会带来一定开销,实际使用要看情况来定。基于链表的栈typedef struct _node { int data; struct _node* next; }node;typedef struct _stack { node *top;...
阅读(212) 评论(0)

操作系统原理:进程地址空间

Linux 进程虚拟地址空间先回忆一下ELF文件的组织结构,可以看这篇文章:Linux 链接与ELF文件。程序执行后进程地址空间布局则和操作系统密切相关。在将应用程序加载到内存空间执行时,操作系统负责代码段与数据段的加载,并在内存中为这些段分配空间。Linux的进程地址空间大致如下: 栈 (stack)函数调用借助的就是栈。Linux中ulimit -s命令可查看和设置堆栈最大值,调高堆栈容量可能...
阅读(674) 评论(0)

操作系统原理:虚拟地址

The Memory Hierarchy存储系统是有层次的,从快到慢依次是:CPU寄存器、静态SRAM、动态DRAM、磁盘。如下图: Inter Core i7的结构如下: Segmentation and Paging在CPU保护模式下,进程使用虚拟地址,这也给每个进程一个大的、一致的私有的地址空间。地址翻译分段与分页相结合:逻辑地址-->[分段]-->线性地址(虚拟地址)-->物理地址。每...
阅读(592) 评论(0)

从汇编角度看C++类的方法访问类成员的原理

C++编译后最终也是生成了机器码,不需要任何解释器或虚拟机来运行。相比C语言,C++有了类class大大的方便了代码结构的组织,使得构建大程序简便了很多。实例化一个类后,类的成员方法就可以访问这个类的成员了,那么从汇编角度看,到底是如何实现的呢?原理也十分简单,类所有成员本质上就是一个结构体,每个类的方法第一个入参就是把这个结构体的地址穿进去,类的方法就是这样实现了访问类的成员。...
阅读(456) 评论(0)

操作系统原理:链接与ELF文件

ELF文件在x86架构下,Linux使用的是ELF(Executable and Linkable Format)目标文件格式。目标文件的三种格式: Relocatable object file. 可重定位目标文件包含二进制代码和数据,编译时可与其他可重定位目标文件合并组成可执行目标文件,如 .o,.a文件。 Executable object file. 可执行目标文件包含二进制代码和数据,可以...
阅读(664) 评论(0)

小练习 - 排序:冒泡、选择、快排

好久没手写过排序了,用C89标准的C重新练习下三种排序方法,快排的边界还是需要注意下。练习这些经典算法要在脑子里能够形象的想象出这些数据结构的表现与操作,这样才能理解深刻。// c89 标准 #include // [begin, end) 前闭后开,索引范围是[begin, end - 1] // 冒泡, 稳定排序 void bubble_sort(int data[], int...
阅读(304) 评论(0)

Linux 同步机制:自旋锁

自旋锁的特点与适用场景Linux自旋锁spinlock同一时刻只能被一个可执行线程持有。当一个线程试图获取一个已经被持有的spin lock时,就会一直忙循环-选择-等待锁重新可用。忙等待免去了线程挂起再被唤醒的转换,省去了两次上下文切换的时间。因而spinlock适合下面的场景:SMP多核系统中,持有自旋锁的时间小于完成两次上下文切换的时间,这种场景使用spinlock效率会比较高。所以一般在用户...
阅读(373) 评论(0)
96条 共5页1 2 3 4 5 ... 下一页 尾页
    个人资料
    • 访问:189963次
    • 积分:2900
    • 等级:
    • 排名:第14448名
    • 原创:96篇
    • 转载:0篇
    • 译文:0篇
    • 评论:39条
    About me
    最新评论