网站运营主要做什么工作,网站内链怎么优化,用wordpress教程视频,织梦网站栏目对应首页一、热补丁简介
一个正在运行的程序#xff0c;要是有某函数或某流程有问题#xff0c;需要修改#xff0c;有两个方式#xff1a;
1.通过设置LD_PRELOAD把需要的库重新定向#xff0c;但这种方式需要重启正在运行的程序。 2.通过修改可执行文件某个函数指向的地址…一、热补丁简介
一个正在运行的程序要是有某函数或某流程有问题需要修改有两个方式
1.通过设置LD_PRELOAD把需要的库重新定向但这种方式需要重启正在运行的程序。 2.通过修改可执行文件某个函数指向的地址指向新的函数这种方式可不重启正在运行的程序。这就热补丁(hotpatch)。
二、热补丁使用
1.API介绍
Linux提供了一套API来动态装载库。热补丁主要使用如下API
- dlopen打开一个库并为使用该库作些准备。
- dlsym在打开的库中查找符号的值。
- dlclose关闭库。在使用一下API时要提前包含头文件**#include dlfcn.h**
dlopen函数原型
void *dlopen(const char *filename, int flags);--filename是你要打开的库路径--flags必须有RTLD_LAZY或者RTLD_NOW其中之一。RTLD_LAZY在dlopen返回前对于动态库中的未定义的符号不执行解析。仅针对函数变量立即解析RTLD_NOW需要在dlopen返回前解析出所有未定义符号如果解析不出来在则会返回NULL和错误。***/*可以和一下参数进行搭配使用*/***--RTLD_GLOBAL动态库中定义的符号可被其后打开的其它库解析。--RTLD_LOCAL与RTLD_GLOBAL作用相反动态库中定义的符号不能被其后打开的其它库重定位。如果没有指明是RTLD_GLOBAL还是RTLD_LOCAL则缺省为RTLD_LOCAL。--RTLD_NODELETE:在dlclose()期间不卸载库并且在以后使用dlopen()重新加载库时不初始化库中的静态变量。--RTLD_NOLOAD不加载库。可用于测试库是否已加载(dlopen()返回NULL说明未加载否则说明已加载也可用于改变已加载库的flag。--RTLD_DEEPBIND在搜索全局符号前先搜索库内的符号避免同名符号的冲突。
返回值是句柄在下面dlsym中使用。dlsym函数原型
void *dlsym(void *handle, const char *symbol);--handle是dlopen返回的句柄。--symbol是你想替换的符号。
返回值是指向替换后函数的地址供调用使用。dlclose函数原型
int dlclose(void *handle);
注意用于关闭指定句柄的动态链接库只有当此动态链接库的使用计数为0时,才会真正被系统卸载。三、热补丁代码示例
要被替换的函数 该文件起名为1.c要先编为1.so。
gcc -fPIC -shared 1.c -o 1.so#include stdio.hint func2()
{printf(1.c_func2\n);return 0;
}int func1()
{func2();printf(1.c_func1\n);return 0;
}需要替换的 该文件起名为2.c编译的时候要加上 -ldl。
gcc 2.c -ldl#include stdio.h
#include dlfcn.h
#include stdlib.hint func2()
{printf(2.c_func2\n);return 0;
}int func1()
{func2();printf(2.c_func1\n);return 0;
}int main()
{void * handle;/*定义一个函数指针指向原函数这样就可以在后面一直使用原函数名了*/int (*func)(void);func func1;/*获得句柄*/handle dlopen(./1.so, RTLD_LAZY);/*原函数*/func();sleep(1);func();sleep(1);/*进行函数替换*/*(void **)(func)dlsym(handle,func1);/*这个时候在打印就已经变了*/func();dlclose(handle);return 0;
}该程序输出
2.c_func2
2.c_func1
2.c_func2
2.c_func1
1.c_func2
1.c_func1四、热补丁补充
1.根据上面代码可以看出如果函数中包含别的函数也是可以替换的。但是如果只有声明没有实现就会段错误。 2.不同进程的是不能替换的就算是函数指针定义在最前面也不可以。 3.再编译的时候不能去符号不要不能替换。
五、热补丁其他方法
1.找个空地址把新函数烧进去然后修改原函数的入口地址。这个方法普遍使用于单片机上。 2.C语言调用lua脚本通过lua脚本进行源代码的替换。这个办法需要业务程序也是lua语言写的。
如果大家还有别的办法也请评论区给我说一下。