本文原地址: http://www.feitianzhi.com/boke/index.php/archives/27/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


概述

      "小雉视频系统"虽采用面向过程对象(参见:http://www.feitianzhi.com/boke/index.php/archives/18/)编程,去除线程池等复杂的设计,并减少线程的使用量,但线程数依然高达40个之多;
      40个线程数虽对cpu而言已没有任何压力了,但多线程的复杂性依然存在,其中线程死锁是多线程中最常见同时也难以定位的问题;


线程死锁产生的原因分析

  1. 能否通过合理的设计规划避免线程死锁?

"小雉视频系统"是一份持续维护并增加新功能的代码,代码的修改必须考虑与老代码的兼容,需要处理的细节多,对每次修改都做出完美的设计几乎是不能实现的;

  1. 能否使用第三方工具查找线程死锁?

对开发阶段就能发现的死锁用第三方工具定位是处理问题的通用方法,但使用第三方工具会导致系统速度指数级别的下降,在生产环境中无法使用,同时"小雉视频系统"模块众多,模块均支持按需开启和关闭,任何一个修改需要准备的测试用例太多,死锁后难以确定与此死锁相关的模块;


理想化设计

  1. 死锁时自动报告是哪些线程卡住了?卡在源码的哪一行?卡时的调用堆栈是什么样?
  2. 可在任意时间接受外部干预,报告所有线程当前执行到哪段源代码的哪行并提供调用堆栈;

小雉视频系统--线程死锁设计预览

  1. 线程死锁时自动报告,"小雉视频系统"并不能判断线程死锁,"小雉视频系统"是做视频应用,5S以上的卡顿足以让用户不满,"小雉视频系统"是监视所有线程,看哪个线程连续5S时间内一直停在同一句代码处,以此认为其死锁了,效果如下:

  1. 任意时间打印所有线程的调用堆栈,"小雉视频系统"监听linux下10的信号,在收到信号后打印所有线程当前的调用堆栈,效果如下:

猜您可能喜欢

小雉系统安装:http://www.feitianzhi.com/boke/index.php/archives/11/
小雉系统网络配置:http://www.feitianzhi.com/boke/index.php/archives/15/
小雉系统硬盘配置:http://www.feitianzhi.com/boke/index.php/archives/16/
小雉系统远程升级:http://www.feitianzhi.com/boke/index.php/archives/14/

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/26/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


概述

      本地拉取相机是"小雉视频系统"自定义的一种相机类型,此相机类型可以使用通过rtsp,gb28181接入的一个到多个视频流作为输入,然后对这些输入的视频源按一定的规则(如旋转,拉伸)绘制在目标图上,实现图像拼接,分辨率和帧率调整等业务;

      本地拉取相机是以"小雉视频系统"本身接入的视频源作为输入源,而"小雉视频系统"是一个单进程应用,多个本地拉取相机对同一个视频拉取是共享同一份内存的,只需解码一次,如有需求对一视频源叠加不同的水印后作为两路新流输出,则可创建两路本地拉取相机实现这一需求;


两种不同水印叠加后作为两路新流输出

  1. 假设"小雉视频系统"已经使用rtsp接入了一路uuid为src的视频流,如下图所示

  2. 新建一路"本地拉取相机",分别命名为out1,拉取src的流,并在左上脚添加out1的水印,如下图所示
  3. 新建一路"本地拉取相机",分别命名为out2,拉取src的流,并在左上脚添加out2的水印,如下图所示

      如上实现了src拉取rtsp视频流,并解码,out1和out2拷贝src解码后的视频分别进行水印叠加后编码,最后输出新的视频流out1和out2.


分辩率和帧率修改

      本处对out1的分辩率和帧率进行修改,如下图


图像旋转

      本处对out1的图像进行旋转30度,如下图


双图像拼接

      本处以out1的图像为例;

  1. 拉取src两次(也可拉取不同的视频源,如out2也能被拉取),如下图
  2. 以下操作比较复杂,这里把out1拖拽出来生成新界面来配置,操作:鼠标左键按住菜单栏的"out1"选项卡拖拽到菜单区以外放开,如下图
  3. 右键"相机配置"选择"切图配置",如下图
  4. 在图新配置上可以对两图像的相对位置进行调整,也能改变其长宽,进行旋转,右键画区域等,如下图的一个示例
  5. 保存配置后,用vlc查看的效果如下

      同此节方法可实现多相机的图像拼接.

猜您可能喜欢

小雉系统安装:http://www.feitianzhi.com/boke/index.php/archives/11/
小雉系统网络配置:http://www.feitianzhi.com/boke/index.php/archives/15/
小雉系统硬盘配置:http://www.feitianzhi.com/boke/index.php/archives/16/
小雉系统远程升级:http://www.feitianzhi.com/boke/index.php/archives/14/

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/25/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


editbin

这是 Visual Studio 2017 采用的做法。我们需要使用到两个工具——editbin 和 dumpbin。前者用于编辑我们编译生成好的程序使之头信息中声明支持大于 2GB 内存,后者用于查看程序的头信息验证我们是否改好了。

编辑一个程序使之声明支持大于 2GB 内存的命令是:

editbin /largeaddressaware xxx.exe

其中,xxx.exe 是我们准备修改的程序,可以使用相对路径或绝对路径(如果路径中出现空格记得带引号)。

验证这个程序是否改好了的命令是:

dumpbin /headers xxx.exe | more

同样,xxx.exe 是我们刚刚改好准备检查的程序,可以使用相对路径或绝对路径。

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/24/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


      目前恩山上本人使用较多的固件为Padavan,PandoraBox,Bootloader部分则使用H大的Breed,这些固件使用起来体验极好,接下来浅谈一下个人对这些固件的看法,若有不当之处,还请指出

Breed部分的介绍将在下文刷机过程中展示

      PandoraBox是基于OpenWrt进行了大量国内路由适配的系统,其界面接近原生系统,并针对国情内置了不少实用的组件,通过opkg管理组件,全面汉化,翻译水平比原生系统高出不少,软件源在国内,所以下载速度较快,时区和信道都按照国内的标准预先修改了,所以对于大部分人来说,直接刷PandoraBox即可,不必费力刷原生OpenWrt,而且据说PandoraBox采用的无线驱动优于原生,对此没有太确定的消息,仅作参考

      Padavan俗称老毛子,其界面友好度极高,非常适合新手入门,不过默认主题略丑,好在可以更换,而且看起来不错,同样针对国情加入了大量组件,对332支持极好,不过扩展性较OpenWrt略有不足,但对于新手来说足矣

      我使用Padavan和PandoraBox近一年,但折腾的心是不会停止的,所以现在准备给R3G刷入原生OpenWrt,但根据OpenWrt官网上的资料和H大的某些回复来看,Breed刷OpenWrt略有困难,其原因在于给OpenWrt提交R3G支持的人,提交的flashlayout跟原厂的不兼容,而且使用了UBI,因此breed无法兼容,故breed不支持直接刷入mir3g的openwrt固件,且无法识别tar包
详情可见下方链接
https://www.right.com.cn/forum/forum.php?mod=viewthread&tid=267455&page=1

      但此楼里有另一位大神提出了一种新的思路,见第三页aatest123的回复,其思路在于通过Breed先刷入initramfs-kernel.bin,这个文件集内核kernel和文件系统rootfs为一体,在引导期间将文件系统放在内存中,但由于内存断电后无法保存数据,所以该系统的所有设置无法保存,仅适用于不驱动flash的情况下使用,我们先通过Breed刷入该临时OpenWrt系统,重启路由器即可进入该临时系统,通过luci界面,选择系统更新,上传安装openwrt-18.06.4-ramips-mt7621-mir3g-squashfs-sysupgrade.tar(此为写此文时最新版本,可更换)
附件在此:https://pan.baidu.com/s/1SkF7WOt5GkIw6f68JP7viA 提取码: npp5

      随后路由器会自动重启,但登录后会发现进入的仍然是临时OpenWrt,这是因为Breed在刷入临时OpenWrt时刷入的是路由器的kernel0,而我们通过临时OpenWrt安装正式系统刷入的是kernel1,接下来我们将路由器断电,进入Breed(具体进入方法见Breed安装),启用环境变量,添加环境变量xiaomi.r3g.bootfw,其值为2,其目的在于使Breed启动后从kernel1启动,接下来重启,即可进入正式版OpenWrt系统,折腾第一步结束

      接下来是我当时安装时各种参考的资料分析,以及遇到的一些坑,毕竟我只能算是一位爱好者,没有接受过计算机技术教学,对于编译等东西一窍不通

      首先说说OpenWrt官网上对于R3G安装的操作,官网上的操作是针对原厂Bootloader和原厂固件的,故对于安装了Breed的我们来说,照抄是万万不行的,官网上提供两个文件,分别是mir3g-squashfs-kernel1.bin和mir3g-squashfs-rootfs0.bin,官网上的命令为:

mtd write mir3g-squashfs-kernel1.binkernel1
mtd write mir3g-squashfs-rootfs0.binrootfs0
nvram set flag_try_sys1_failed=1
nvram commit
reboot

      上述命令中nvram是uboot专有命令,Breed与uboot相互独立,参数不共用,根据国外论坛对于小米路由器原厂uboot的分析,小米路由器的kernel0包含的usb恢复的功能,就是将官方固件命名为miwifi.bin放入U盘内,断电时插入路由器,用硬物抵住reset键后插电,保持10秒左右,待黄灯快速闪动后可松手,可恢复至官方固件,这个功能可用于原厂固件损坏后的修复,也算是不错的功能,所以OpenWrt官网上的建议是将内核文件刷入kernel1

      接下来说说Breed的参数,根据H大的回复,breed的启动流程如下:
      如果kernel0存在kernel1不存在,那么启动kernel0
      如果kernel1存在kernel0不存在,那么启动kernel1
      如果kernel0和kernel1都存在,那么检查环境变量 xiaomi.r3g.bootfw的值,如果存在且值为2,那么启动kernel1,否则启动kernel0

      关于操作前的备份指令
      cat /proc/mtd:读取路由器内部分区
      插入U盘(FAT/FAT32)
      输入【df -h】查看查看U盘的分区路径
      或者输入"cd /"回车,再输入"ls -a"查看到extdisks文件,再"cd extdisks"进入到extdisks文件里用"ls -a"就能查看到你的U盘路径,我的是sda4,以下以我自己U盘的路径为例:
      备份(请自行修改回你自己的U盘路径):

dd if=/dev/mtd0 of=/extdisks/sda4/ALL.bin
dd if=/dev/mtd1of=/extdisks/sda4/Bootloader.bin
dd if=/dev/mtd2of=/extdisks/sda4/Config.bin
dd if=/dev/mtd3 of=/extdisks/sda4/Bdata.bin
dd if=/dev/mtd4of=/extdisks/sda4/Factory.bin
dd if=/dev/mtd5 of=/extdisks/sda4/crash.bin
dd if=/dev/mtd6 of=/extdisks/sda4/crash_syslog.bin
dd if=/dev/mtd7of=/extdisks/sda4/reserved0.bin
dd if=/dev/mtd8of=/extdisks/sda4/kernel0.bin
dd if=/dev/mtd9of=/extdisks/sda4/kernel1.bin
dd if=/dev/mtd10of=/extdisks/sda4/rootfs0.bin
dd if=/dev/mtd11of=/extdisks/sda4/rootfs1.bin
dd if=/dev/mtd12of=/extdisks/sda4/overlay.bin
dd if=/dev/mtd13of=/extdisks/sda4/ubi_rootfs.bin
dd if=/dev/mtd14 of=/extdisks/sda4/data.bin

      备份到最后一个mtd14可以会出现如下出错提示:
dd: can't open '/dev/mtd14': Device or resourcebusy
      该分区备份不成功无所谓,关键的mtd0-mtd4备份下来就行了。
      如果还在官版的固件下想恢复的,可使用如下命令:
      恢复(这里我们不需要该步骤,只是给有需要的人看的官版固件下的恢复步骤)

mtd write /extdisks/sda4/Bootloader.binBootloader
mtd write /extdisks/sda4/Config.bin Config
mtd write /extdisks/sda4/Bdata.bin Bdata
mtd write /extdisks/sda4/Factory.binFactory
mtd write /extdisks/sda4/crash.bin crash
mtd write /extdisks/sda4/crash_syslog.bincrash_syslog
mtd write /extdisks/sda4/reserved0.binreserved0
mtd write /extdisks/sda4/kernel0.binkernel0
mtd write /extdisks/sda4/kernel1.bin kernel1
mtd write /extdisks/sda4/rootfs0.binrootfs0
mtd write /extdisks/sda4/rootfs1.binrootfs1
mtd write /extdisks/sda4/overlay.binoverlay
mtd write /extdisks/sda4/ubi_rootfs.binubi_rootfs
mtd write /extdisks/sda4/data.bin data

Breed

      https://www.right.com.cn/forum/thread-161906-1-1.html
      这是一个非常易用的Bootloader,针对刷机主流型号进行了适配,内置DHCP服务,拥有Web图形化界面,小白也能轻松刷机,并且支持Telnet,wget等功能,可以通过TTL进行操作,具体介绍可见上述网址,选择仅看楼主,里面包含绝大多数关于Breed的资料,就不在此赘述

      如何在R3G内刷入Breed

      首先小米路由器需要开启ssh,此类教程在网上极多,是基本功,在此不多说了
      首先需要下载支持小米路由器3G的Breed,可从H大搭建的服务器https://breed.hackpascal.net/ 内下载,其型号是breed-mt7621-xiaomi-r3g.bin
      接下来通过WinSCP将文件上传至路由器内部,注意将文件协议选择为SCP,我通常将文件上传至/tmp目录下,建议将文件改名为Breed.bin,便于后续操作
      输入mtd write /tmp/breed.bin Bootloader,将Breed刷入Bootloader
若输入mtd -r write /tmp/breed.bin Bootloader,-r意味着刷入后直接重启,一旦刷错难以补救,所以建议不要加入-r,待完      全确认后再手动断开电源
      在接入电源线之前用硬物顶住路由的reset键再接电,等到路由器的指示灯狂闪的时候,松开reset键,电脑上在浏览器中输入192.168.1.1,即可进入Breed控制台

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/23/
转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


使用 GRUB2 安装 Ubuntu 18.04

      使用 GRUB2 安装 Ubuntu 18.04 的原因是机器上已经有 Ubuntu 16.04 在了,GRUB 引导自然也是有的。我以往常使用传统硬盘安装的方式, GRUB2 本身是硬盘安装的一种方式,只是引导器选择了GRUB2。好处是只要有 ISO 的安装镜像就可以了,不需要像传统的方法从源里新下载适用于硬盘的引导 vmlinux & initrd, 它们俩一般在 hd-media 目录,如下是阿里云 Ubuntu 18.04 的路径。

      https://mirrors.aliyun.com/ubuntu/dists/bionic/main/installer-amd64/current/images/hd-media/

流程

  • 下载 Ubuntu 18.04 镜像,更名为 Ubuntu-18.04.iso, 放在某盘根目录。
  • 进入 GRUB2, 在界面按提示 C 进入 Command Mode
  • ls (hdxx, msdosxx)/, 寻找 Ubuntu-18.04.iso 的存放路径。本次为 (hd2, msdos1)
  • 执行指令

    loopback loop (hd2, msdos1)/Ubuntu-18.04.iso
    linux (loop)/casper/vmlinuz boot=casper iso-scan/filename=/Ubuntu-18.04.iso
    initrd (loop)/casper/initrd.lz
    boot

说明:

(loop)后的路径,依据 vmlinuz & initrd.lz 实际的来。可以 tab 自动补全,或 ls 查看。
linux 指令后,没有增加其它指令(quiet splash)。好处是在运行过程中,有 LOG 。解决了我因为打印机连接而 Pending 的问题。

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/22/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


概述

      VPN是一种非常成熟的技术,各大操作系统都默认支持pptp,l2tp等技术,但这些技术的使用成本过高,如pptp依赖GRE,l2tp有特殊的关键字,在通信过程中存在被截断的可能;

      KVPN并不仅是为解决传统vpn的缺陷而开发,KVPN是为优化网络速度而开发,KVPN同时支持tcp,udp,http的传输协议,在使用过程中自动选择最优路线进行通信(问:http比tcp优?答:http是为利用历史原因出现的http cdn加速,让本只支持http的cdn加速为我其他应用服务);

KVPN应用场景

  1. 穿透性要求:kvpn数据流无特殊固定的关键字,同时支持动态的数据扰乱,让数据流不具备可识别性,承载方式同时支持tcp,udp,http,数据与普通数据亲近,让数据具备极强的穿透性(延伸扩展:把数据封装于http承载的jpg图片中--只要能用http请求图片的网络都能过,把数据封装在h264,h265视频流中--这样能支持rtsp,rtmp,hls,gb28181的网都能过);
  2. TCP加速要求:tcp是系统实现的可靠传输,重传机制和效率受系统的影响,在总带宽有限的条件下(如果只有我一个人用是够的条件下),如何保证自己的业务畅快运行(实现不公平竞争),是招标pk时经常需要面对的问题;kvpn在进行vpn数据传输时,对tcp数据进行识别,在数据还未发出时就假冒对放作出tcp的回执确认,让系统永远认为网络非常顺畅,kvpn再自己把假冒的数据使用udp(加冗余,快速丢包重传,抢占他人带宽--平时大家都用过迅雷抢带宽)把数据发给对端,实现数据快速通信;
  3. 改善udp效果:udp是不可靠通信,在网络差时会丢包,会对业务产生影响(有的应用程序只能在好的网络下可正常运行--使用udp但没有重传机制),kvpn是基于本机不丢包的前提,在网络传输过程中使用可靠的tcp或带重传机制的udp进行数据传输,保证业务的正常运行;
  4. 低成本的网络加速:因历史原因到一些地方的服务器的延时高,速度慢,而在目前互联网洪水下浮枝(免费资源)的拾取成本较低,其中免费的http cdn加速就是一个很好的选择,kvpn可以把数据封装在http中进行传输,利用免费的cdn进行加速;
  5. 协议识别的再次分发:对于代理软件的开发成本与协议相关,如rtsp代理,代理需要拉取rtsp再对rtsp进行转发,开发需要实现rtsp的完整协议,开发成本高,那可以只识别rtsp的第一条指令,根据指令动态映射到指定服务器吗?使用kvpn在“小雉视频系统”中通过实现视频协议的识别和ip包级别动态路由来实现各种视频应用是kvpn开发的最主要的目的,此部分属于“小雉视频系统”中的高级开发;

KVPN的简单使用

本处提供简单的kvpn测试demo,并提供在centos7(小雉系统中也集成了此demo,可使用小雉系统测试)下的使用教程

  1. 下载kvpn,https://download.csdn.net/download/zhangrui_fslib_org/11693940
  2. 运行服务端
    kvpn服务端
    监听16899端口,允许用户名:user,密码:pwd登录系统
    在客户端认证成功后,本机使用1.1.1.1的ip,分配2.2.2.2给客户端使用
  3. 运行客户端
    kvpn客户端
    使用用户名:user,密码:pwd登录服务器10.172.100.81:16899
  4. 查看服务端结果
    kvpn服务端运行结果
  5. 查看客户端结果
    kvpn客户端运行结果

小雉系统中的VPN使用

小雉系统除集成KVPN外,为与各操作系统集成还集成了PPTP和L2TP,关于小雉系统您需要浏览以下文章:
小雉系统安装:http://www.feitianzhi.com/boke/index.php/archives/11/
小雉系统网络配置:http://www.feitianzhi.com/boke/index.php/archives/15/
小雉系统硬盘配置:http://www.feitianzhi.com/boke/index.php/archives/16/
小雉系统远程升级:http://www.feitianzhi.com/boke/index.php/archives/14/

  • 在小雉系统中使用pptp或l2tp,以使用10.172.100.81作为服务器

服务器配置



客户端配置,以windows为例




  • kvpn的使用

服务器配置,以10.172.100.81作为服务器



客户端配置,以10.172.100.82作为客户端


本文原地址: http://www.feitianzhi.com/boke/index.php/archives/21/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


参考文章:https://www.oschina.net/question/234345_52687

用例子说话

二进制

对应源码

有一个程序

a.out

main.c

需要加载插件A

libA.so

liba.c

A需要另一个动态库

libB.so

libB1.c 或 libB2.c

本文的关注点就是:到底是哪一个libB.so被加载

目录结构:

/home/debao/ttt/a.out
/home/debao/ttt/libA.so
/home/debao/ttt/libB.so
/usr/lib/libB.so
具体源码
main.c ==> ./a.out

include <stdio.h>

include <dlfcn.h>

typedef int (*funcA)(int, int);
int main()
{

void * plugin = dlopen("./libA.so", RTLD_LAZY);
funcA f = (funcA)dlsym(plugin, "funcA");
printf("main: %d\n", f(3,4));
return 0;

}
liba.c ==> ./libA.so

include <stdio.h>

int funcB(int, int);
int funcA(int a, int b)
{

printf("hello from funcA\n");
return funcB(a, b);

}
libb1.c ==> ./libB.so

include <stdio.h>

int funcB(int a, int b)
{

printf("Hello from funcB 1\n");
return a*b;

}
libb2.c ==> /usr/lib/libB.so

include <stdio.h>

int funcB(int a, int b)
{

printf("Hello from funcB 2\n");
return a*b;

}
编译库文件
编译动态库libB.so

$ gcc -shared -fPIC libb2.c -o libB2.so
$ sudo mv libB2.so /usr/lib/libB.so
$ gcc -shared -fPIC libb.c -o libB.so
编译动态库libA.so

$ gcc -shared -fPIC liba.c -o libA.so -L. -lB
顺便看看该elf文件的头部信息:

$ readelf libA.so -d

Dynamic section at offset 0xf20 contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libB.so]
0x00000001 (NEEDED) Shared library: [libc.so.6]
...
恩,只有库的文件名信息,而没有路径信息。

编译程序
第一次编译运行(什么路径都不加)

$ gcc main.c -ldl
$ ./a.out
hello from funcA
Hello from funcB 2
main: 12
程序:dlopen从当前目录找到libA.so,然后却在/usr/lib/中找到libB.so(没有使用当前目录的libB.so,这是我们需要的么?)

第二次编译运行(使用DT_RPATH)

$ gcc main.c -ldl -Wl,--rpath=.
$ ./a.out
hello from funcA
Hello from funcB 1
main: 12
恩,使用当前目录的libB.so,很理想的东西

可是,由于DT_RPATH无法被环境变量LD_LIBRARY_PATH覆盖,不是不建议被使用,而是建议使用DT_RUNPATH么?

第三次编译运行(使用DT_RUNPATH)

$ gcc main.c -ldl -Wl,--rpath=.,--enable-new-dtags
$ ./a.out
hello from funcA
Hello from funcB 2
main: 12
问题重新出现,使用的系统路径中的libB.so 而不是当前目录下的。

程序头部信息
通过下列命令可以查看:

$ readelf -d a.out
为了完整起见,列出前面3次编译的程序的信息:

没有rpath和runpath

Dynamic section at offset 0xf20 contains 21 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000c (INIT) 0x8048360
...
包含rpath

Dynamic section at offset 0xf18 contains 22 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000f (RPATH) Library rpath: [.]
0x0000000c (INIT) 0x8048360
....
包含rpath和runpath

Dynamic section at offset 0xf10 contains 23 entries:
Tag Type Name/Value
0x00000001 (NEEDED) Shared library: [libdl.so.2]
0x00000001 (NEEDED) Shared library: [libc.so.6]
0x0000000f (RPATH) Library rpath: [.]
0x0000001d (RUNPATH) Library runpath: [.]
原因
RPATH and RUNPATH给出这个问题的答案:

Unless loading object has RUNPATH:

RPATH of the loading object,
    then the RPATH of its loader (unless it has a RUNPATH), ...,
    until the end of the chain, which is either the executable
    or an object loaded by dlopen
Unless executable has RUNPATH:
    RPATH of the executable

LD_LIBRARY_PATH
RUNPATH of the loading object
ld.so.cache
default dirs
用它解释第一个程序:

libA.so 没有RUNPATH,故而
使用其RPATH (没有)
递归查找其loader直到链条的顶端(可执行程序或被dlopen打开的对象)的RPATH或者遇RUNPATH退出 (没有命中)
可执行程序没有RUNPATH,故而
使用其RPATH (没有)
环境变量LD_LIBRARY_PATH,(没有)
libA.so 的RUNPATH (没有)
ld.so.cache (没有命中)
默认路径/usr/lib (命中)
用它解释第二个程序:

libA.so 没有RUNPATH,故而
使用其RPATH (没有)
递归查找其loader直到链条的顶端(可执行程序或被dlopen打开的对象)的RPATH或者遇RUNPATH退出 (没有命中)
可执行程序没有RUNPATH,故而
使用其RPATH (命中)
用它解释第三个程序:

libA.so 没有RUNPATH,故而
使用其RPATH (没有)
递归查找其loader直到链条的顶端(可执行程序或被dlopen打开的对象)的RPATH或者遇RUNPATH退出 (没有命中)
可执行程序有RUNPATH,(继续前行)
环境变量LD_LIBRARY_PATH,(没有)
libA.so 的RUNPATH (没有)
ld.so.cache (没有命中)
默认路径/usr/lib (命中)
有意思的就是这个程序了,可执行程序的RUNPATH是一个重要的判断条件,却并不被做为这儿搜索路径!!

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/20/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


本文纯探讨技术实现,请大家抱着学习交流之目的进行阅览。

-rpath和-rpath-link的区别

(1)-rpath和-rpath-link都可以在链接时指定库的路径;
(2)运行可执行文件时,-rpath-link指定的路径不再有效(链接器没有将库的路径包含进可执行文件中),
           而-rpath指定的路径还有效(因为链接器已经将库的路径包含在可执行文件中);
(3)-L指定的是链接时的库路径,生成的可执行文件在运行时库的路径仍由LD_LIBRARY_PATH环境变量指定;

(4)不管采用何种选项链接,当提示找不到动态库时均可通过设置LD_LIBRARY_PATH解决。
其中 $$ORIGIN表示文件的当前路径,./表示应用程序的路径,一般-rpath,'$$ORIGIN'才能获得想要的效果;
-rpath,'$$ORIGIN',--enable-new-dtags 会在程序中加再加(RUNPATH)标签,参考http://www.feitianzhi.com/boke/index.php/archives/21/

gcc -ffunction-sections -fdata-sections -Wl,–gc-sections 减小程序体积

GCC链接操作是以section作为最小的处理单元,只要一个section中的某个符号被引用,该section就会被加入到可执行程序中去。因此,GCC在编译时可以使用 -ffunction-sections 和 -fdata-sections 将每个函数或符号创建为一个sections,其中每个sections名与function或data名保持一致。而在链接阶段, -Wl,–gc-sections 指示链接器去掉不用的section(其中-wl, 表示后面的参数 -gc-sections 传递给链接器),这样就能减少最终的可执行程序的大小了。
我们常常使用下面的配置启用这个功能:

CFLAGS += -ffunction-sections -fdata-sections
LDFLAGS += -Wl,--gc-sections

让make更透明些

在编译信息里面看到详细的gcc/g++的编译参数

make VERBOSE=1

在CMakeLists.txt里面加上这句指令也可以

set(CMAKE_VERBOSE_MAKEFILE ON)

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/19/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


本文纯探讨技术实现,请大家抱着学习交流之目的进行阅览。

测试环境:
服务器端:CentOS 7.0、openvpn-2.3.10
客户端 :Fedora 23

服务器端安装与配置:
安装obfsproxy
1、[root@1st ~]# yum install gcc python-pip python-devel
2、[root@1st ~]# pip install obfsproxy
3、[root@1st ~]# obfsproxy
usage: obfsproxy [-h] [-v] [–log-file LOG_FILE]
[–log-min-severity {error,warning,info,debug}] [–no-log]
[–no-safe-logging] [–data-dir DATA_DIR] [–proxy PROXY]
{managed,obfs2,dummy,obfs3,scramblesuit,b64} …
以上三步,我们就完成了obfsproxy的安装工作,接下来我们开始配置。obfsproxy一般使用obfs3或者scramblesuit模式,scramblesuit是obfs3的加强版,使用密码加密。这样就无法模拟obfs客户端来探测被混淆的是什么。下面以scramblesuit作为示范。
注意:scramblesuit的密码必须为BASE32字符。
BASE32字符是由:ABCDEFGHIJKLMNOPQRSTUVWXYZ234567组成,且必须为32位。

[root@1st ~]# obfsproxy –data-dir ~/.obfs/ scramblesuit –dest 127.0.0.1:1194 –password ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 server 0.0.0.0:1234 &

由于我们是通过obfsproxy来实现服务器端与客户端之间的加密通信,所以openvpn不用监听在服务器端的IP地址上,可以监听在127.0.0.1这样的本地地址。上面的命令中:127.0.0.1:1194就是需要被混淆的端口(协议),0.0.0.0:1234是混淆后对外监听的端口。如果不需要后台运行则去掉最后的 & 。

运行成功后应该会提示:

2015-08-21 22:54:12,282 [WARNING] Obfsproxy (version: 0.2.13) starting up.
2015-08-21 22:54:12,282 [ERROR]

Do NOT rely on ScrambleSuit for strong security!

至此服务端已经配置完成。

客户端安装与配置
关于在Windows和Fedora 23下的openvpn客户端配置,不再本文的讨论范围之内。
Windows客户端
首先:需要在python官方网站上下载你windows对应python版本,本文中下载的是python-2.7.11.amd64,因为测试系统是windows 7 64位。
其次:需要在http://www.voidspace.org.uk/python/modules.shtml这个网站下载pycrypto-2.6.win-amd64-py2.7,如果没有这个文件,将会在安装obfsproxy是报错。
第三:在正确安装上述两个软件后,需要从新启动一下你的操作系统。
第四:在命令行状态下执行:C:\>pip install obfsproxy,如果一切顺利,就可以执行下面的命令了:
c:>obfsproxy scramblesuit –dest xxx.xxx.xxx.xxx(此处是openvpn所在服务器的IP地址):1234 –password ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 client 127.0.0.1:56789 &

fedora 23客户端
首先,用dnf命令检查python-crypto.x86_64、gcc.x86_64、redhat-rpm-config软件包是否安装,如果没有安装,请参照下面的命令进行安装。
[root@f23 ~]# dnf install python-crypto.x86_64
[root@f23 ~]# dnf install gcc.x86_64
[root@f23 ~]# dnf install redhat-rpm-config
[root@f23 ~]# sudo dnf install redhat-rpm-config
此命令解决:gcc: error: /usr/lib/rpm/redhat/redhat-hardened-cc1: No such file or directory的报错

[root@f23 ~]# pip install obfsproxy
[root@f23 ~]# obfsproxy scramblesuit –dest xxx.xxx.xxx.xxx(此处是openvpn所在服务器的IP地址):1234 –password ABCDEFGHIJKLMNOPQRSTUVWXYZ234567 client 127.0.0.1:56789(此处的端口号何以随意指定,不超出范围就好)

在本地客户端,我们通过obfsproxy将所有流量发给服务器端obfsproxy监听的端口,再由obfsproxy重定向到 OpenVPN,这样OpenVPN客户端就不知道服务器IP是多少,没办法对到 OpenVPN 服务器的流量进行特殊处理,所以我们需要手动将到服务器的路由固定下来,假设你的服务器端IP为xxx.xxx.xxx.xxx,本地客户端的网关地址是192.168.1.1,我们以fedora 23为例,添加路由的命令:
[root@f23 ~]# route add -host xxx.xxx.xxx.xxx gw 192.168.1.1(这一点非常重要)

OK,万事具备,祝大家有一个愉快的开始!

本文原地址: http://www.feitianzhi.com/boke/index.php/archives/18/

转载请注明出处,有疑问或错误请发邮件到[email protected] 或加QQ群:869598376


概述

对一个软件的运行占用的资源进行统计,可得到资源占用的"均值"和"峰值",从性能的角度评估软件的框架,自认为可分三个层次:

  1. 峰值架构:按这种架构设计的软件需要按资源使用的峰值配置硬件,一些云服务商(如阿里云)评估的cpu均值与峰值比为2:10,基于此数据,云服务器商可提供更高的突发性能(这也是阿里云服务器测试时感觉比其他云服务器商快的原因);
  2. 总线式峰值架构:如选用高于软件资源消耗均值但低于软件资源消耗峰值的硬件,在软件峰值时不仅会卡顿影响体验且会丢失数据,影响最终结果;"总线式峰值架构"是把数据采集(数据采集的资源消耗肯定是低于均值的)和处理分开,把采到的数据进行缓存再分发给各处理模块处理(处理模块排队完成);
  3. 均值架构:目标是可选用性能略大于软件资源消耗的均值的硬件,实现硬件资源的利用最大化;"总线式峰值架构"相对"峰值架构"会增加业务流程,增大储存资源消耗,而"均值架构"相对"峰值架构"不会增加业务处理流程,同时可合并同类业务的排列顺序,让数据更好地类数组化,增加cpu或储存设备cache的命中率,进一步提升性能,降低软件资源消耗的均值;

直接均值架构

"小雉视频系统"采用"均值架构",同时"小雉视频系统"是单进程设计,数据在多模块之间传递采用引用方式完成,所有操作都能直接完成;
合理的算法让数据的移除和插入使用位于链表的头和尾,保持数据的数组特性,提高cpu缓存命中;
合理的业务分解让数据快速被过滤,大大减少堆积数据量,据统计视频中可能感兴趣的数据不足10%;
采用"直接均值架构"的"小雉视频系统"的硬件利用率可达90%,即cpu均值达90%不会影响使用体验;