【Linux】库制作与原理

库制作与原理


文章目录

  • 库制作与原理
  • 一、什么是库
  • 四个总结
  • 二、静态库
    • [2.1 静态库生成](#2.1 静态库生成)
    • [2.2 静态库使用](#2.2 静态库使用)
  • 三、动态库
    • [3.1 动态库生成](#3.1 动态库生成)
    • [3.2 动态库使用](#3.2 动态库使用)
    • [3.3 库运行搜索路径](#3.3 库运行搜索路径)
  • 五、目标文件
  • 六、ELF文件
  • 七、ELF从形成到加载轮廓
    • [7.1 ELF形成可执行](#7.1 ELF形成可执行)
    • [7.2 ELF可执行文件加载](#7.2 ELF可执行文件加载)
  • 八、理解链接与加载
    • [8.1 静态链接](#8.1 静态链接)
    • [8.2 ELF加载与进程地址空间](#8.2 ELF加载与进程地址空间)
      • [8.2.1 虚拟地址/逻辑地址](#8.2.1 虚拟地址/逻辑地址)
      • [8.2.2 重新理解进程虚拟地址空间](#8.2.2 重新理解进程虚拟地址空间)
    • [8.3 动态链接与动态库加载](#8.3 动态链接与动态库加载)
      • [8.3.1 进程如何看到动态库](#8.3.1 进程如何看到动态库)
      • [8.3.2 进程间如何共享库](#8.3.2 进程间如何共享库)
      • [8.3.3 动态链接](#8.3.3 动态链接)
        • [8.3.3.1 概要](#8.3.3.1 概要)
        • [8.3.3.2 我们的可执行程序被编译器动了手脚](#8.3.3.2 我们的可执行程序被编译器动了手脚)
        • [8.3.3.3 动态库中的相对地址](#8.3.3.3 动态库中的相对地址)
        • [8.3.3.4 我们的程序怎么和库具体映射起来的](#8.3.3.4 我们的程序怎么和库具体映射起来的)
        • [8-3-3-5 我们的程序,怎么进⾏库函数调⽤](#8-3-3-5 我们的程序,怎么进⾏库函数调⽤)
        • [8-3-3-6 全局偏移量表GOT(global offset table)](#8-3-3-6 全局偏移量表GOT(global offset table))
        • [8-3-3-7 库间依赖](#8-3-3-7 库间依赖)
      • [8.3.4 总结](#8.3.4 总结)

一、什么是库





预备工作,准备好历史封装的libc代码,在任意新增"库文件"

代码如下(示例):

c 复制代码
// my_stdio.h
#pragma once
#define SIZE 1024
#define FLUSH_NONE 0
#define FLUSH_LINE 1
#define FLUSH_FULL 2
struct IO_FILE
{
int flag; // 刷新⽅式
int fileno; // ⽂件描述符
char outbuffer[SIZE];
int cap;
int size;
// TODO
};
typedef struct IO_FILE mFILE;
mFILE *mfopen(const char *filename, const char *mode);
int mfwrite(const void *ptr, int num, mFILE *stream);
void mfflush(mFILE *stream);
void mfclose(mFILE *stream);
// my_stdio.c
#include "my_stdio.h"
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
mFILE *mfopen(const char *filename, const char *mode)
{
int fd = -1;
if(strcmp(mode, "r") == 0)
{
fd = open(filename, O_RDONLY);
}
else if(strcmp(mode, "w")== 0)
{
fd = open(filename, O_CREAT|O_WRONLY|O_TRUNC, 0666);
}
else if(strcmp(mode, "a") == 0)
{
fd = open(filename, O_CREAT|O_WRONLY|O_APPEND, 0666);
}
if(fd < 0) return NULL;
mFILE *mf = (mFILE*)malloc(sizeof(mFILE));
if(!mf)
{
close(fd);
return NULL;
}
mf->fileno = fd;
mf->flag = FLUSH_LINE;
mf->size = 0;
mf->cap = SIZE;
return mf;
}
void mfflush(mFILE *stream)
{
if(stream->size > 0)
{
// 写到内核⽂件的⽂件缓冲区中!
write(stream->fileno, stream->outbuffer, stream->size);
// 刷新到外设
fsync(stream->fileno);
stream->size = 0;
}
}
int mfwrite(const void *ptr, int num, mFILE *stream)
{
// 1. 拷⻉
memcpy(stream->outbuffer+stream->size, ptr, num);
stream->size += num;
// 2. 检测是否要刷新
if(stream->flag == FLUSH_LINE && stream->size > 0 && stream-
>outbuffer[stream->size-1]== '\n')
{
mfflush(stream);
}
return num;
}
void mfclose(mFILE *stream)
{
if(stream->size > 0)
{
mfflush(stream);
}
close(stream->fileno);
}
// my_string.h
#pragma once
int my_strlen(const char *s);
// my_string.c
#include "my_string.h"
int my_strlen(const char *s)
{
const char *end = s;
while(*end != '\0')end++;
return end - s;
}

四个总结


二、静态库

2.1 静态库生成



2.2 静态库使用


三、动态库

3.1 动态库生成



3.2 动态库使用


3.3 库运行搜索路径


五、目标文件






六、ELF文件





七、ELF从形成到加载轮廓

7.1 ELF形成可执行



注意:实际合并是在链接时进行的,但是并不是这么简单的合并,也会
涉及对库的合并!


7.2 ELF可执行文件加载






八、理解链接与加载

8.1 静态链接





8.2 ELF加载与进程地址空间

8.2.1 虚拟地址/逻辑地址


8.2.2 重新理解进程虚拟地址空间

ELF在被编译好之后,会把自己未来程序的入口地址记录在
ELF header的Entry字段中


8.3 动态链接与动态库加载

8.3.1 进程如何看到动态库


8.3.2 进程间如何共享库


8.3.3 动态链接

8.3.3.1 概要

8.3.3.2 我们的可执行程序被编译器动了手脚




8.3.3.3 动态库中的相对地址

8.3.3.4 我们的程序怎么和库具体映射起来的

8-3-3-5 我们的程序,怎么进⾏库函数调⽤

8-3-3-6 全局偏移量表GOT(global offset table)


8-3-3-7 库间依赖





8.3.4 总结


相关推荐
小小管写大大码3 小时前
如何让vscode变得更智能?vscode接入claude实现自动编程
运维·ide·vscode·自动化·编辑器·ai编程·腾讯云ai代码助手
嵩山小老虎3 小时前
Windows 10/11 安装 WSL2 并配置 VSCode 开发环境(C 语言 / Linux API 适用)
linux·windows·vscode
Fleshy数模4 小时前
CentOS7 安装配置 MySQL5.7 完整教程(本地虚拟机学习版)
linux·mysql·centos
zhang133830890754 小时前
CG-09H 超声波风速风向传感器 加热型 ABS材质 重量轻 没有机械部件
大数据·运维·网络·人工智能·自动化
a41324474 小时前
ubuntu 25 安装vllm
linux·服务器·ubuntu·vllm
JMchen1235 小时前
现代Android图像处理管道:从CameraX到OpenGL的60fps实时滤镜架构
android·图像处理·架构·kotlin·android studio·opengl·camerax
Fᴏʀ ʏ꯭ᴏ꯭ᴜ꯭.5 小时前
Keepalived VIP迁移邮件告警配置指南
运维·服务器·笔记
物联网软硬件开发-轨物科技5 小时前
【轨物洞见】告别“被动维修”!预测性运维如何重塑老旧电站的资产价值?
运维·人工智能
程序员允诺5 小时前
[DevOps实战] 彻底解决依赖地狱:如何编译全静态、可移植的 Xorriso 工具
运维·devops
酣大智5 小时前
接口模式参数
运维·网络·网络协议·tcp/ip