分类目录归档:技术文献

用DISM命令备份与还原Windows系统

由于DISM命令不支持热备份,所以系统备份与还原需要在win7pe、win8pe或第二系统(Win7或Win8)中以管理员身份运行cmd。注:pe系统不能过分精简。
Win8对DISM命令进行了升级,通过把Win8系统 C:\Windows\System32 中的 Dism 文件夹与 Dism.exe 复制到Win7系统(包括PE) C:\Windows\System32 下,Win7就可以使用DISM所有命令了。
Win7要使用以下命令,需要Win8的dism文件。

一、初始备份
Dism /Capture-Image /ImageFile:D:\backup\system.wim /CaptureDir:C:\ /Name:Backup-1 /Description:xxxxxx
参数说明:
/Capture-Image - 将驱动器的映像捕获到新的WIM文件中,捕获的目录包含所有子文件夹和数据。
/ImageFile - 指定映像文件路径。上面这条命令的指定映像文件路径为“D:\backup\system.wim”
/CaptureDir - 指定捕获目录。上面这条命令的指定捕获目录为“C:\”
/Name - 指定名称。此项不能省略。上面这条命令的指定名称为“Backup-1”
/Description - 指定描述。此项可省略。上面这条命令的“xxxxxx”可以改为你想要的描述
上面这条命令代表将C盘内容备份至D:\backup下的system.wim中。

二、增量备份
Dism /Append-Image /ImageFile:D:\backup\system.wim /CaptureDir:C:\ /Name:Backup-2 /Description:xxxxxx
参数说明:
/Append-Image - 将其他映像添加到WIM文件中。这里的wim文件是初始备份生成的wim文件。
其余参数与初始备份相同。
上面这条命令代表将C盘内容增量备份至D:\backup下的system.wim中。

三、系统还原
Dism /Apply-Image /ImageFile:D:\backup\system.wim /Index:2 /ApplyDir:C:\
参数说明:
/Apply-Image - 应用一个映像。上面这条命令的应用映像指D:\backup下的system.wim
/ApplyDir - 指定应用目录。上面这条命令的指定应用目录为“C:\”
/Index - 指定索引。此项不能省略。上面这条命令的指定索引为第二个备份
上面这条命令代表将D:\backup下的system.wim还原至C盘。
因Dism安装WIM映像不会像Ghost那样格式化磁盘,所以如果需要可以自己格式化系统盘。还原后如果发现缺少启动引导文件,可以通过“bcdboot C:\windows /s C: /l zh-cn”指令添加启动引导。/s 指的是系统分区,/l 指的是语言。

四、获取WIM文件映像信息
Dism /Get-WimInfo /Wimfile:D:\backup\system.wim
参数说明:
/Get-WimInfo - 显示有关WIM文件中的映像的信息。
/Wimfile - 指定WIM文件路径。上面这条命令的指定WIM文件路径为“D:\backup\system.wim”
上面这条命令代表查看D:\backup下的system.wim的映像信息。
可以在后面添加索引号或名称来查看某次备份的详细信息,还可以在后面添加 >d:\list.txt 把信息导出为记事本,方便查看。如:
Dism /Get-WimInfo /Wimfile:D:\backup\system.wim /Index:1 >d:\list.txt
或:Dism /Get-WimInfo /Wimfile:D:\backup\system.wim /Name:Backup-1 >d:\list.txt

五、从具有多个卷映像的WIM文件中删除指定的卷映像
Dism /Delete-Image /ImageFile:D:\backup\system.wim /Index:2
参数说明:
/Delete-Image - 从具有多个卷映像的WIM文件删除指定的卷映像。
上面这条命令代表删除D:\backup下的system.wim的第二个备份。
此命令仅删除卷映像名称与描述,而不会删除卷映像数据,因此不会减小映像体积。可用于防止误应用该卷映像。要减小映像的体积可以通过下面的命令完成。

六、从具有多个卷映像的WIM文件中提取单独的卷映像
Dism /Export-Image /SourceImageFile:D:\backup\system.wim /SourceIndex:2 /DestinationImageFile:D:\backup\system-2.wim
参数说明:
/Export-Image - 将指定映像的副本导出到其他文件。
/SourceImageFile - 指定映像文件来源路径。上面这条命令的指定映像文件来源路径为“D:\backup\system.wim”
/SourceIndex - 指定来源索引。上面这条命令的指定来源索引为第二个备份
上面这条命令代表将D:\backup下的system.wim的第二个备份提取出来,存至D:\backup下的system-2.wim。
如果原来的映像有3个索引,可以通过该命令将第一个和第三个提取出来(只需将上面这条命令的/SourceIndex:2分别改为/SourceIndex:1和/SourceIndex:3),存至D:\backup下的system-2.wim。修改后,卷映像的索引号会发生改变,但名称不会变。

附:
默认情况下,DISM.exe工具将排除以下文件:
[ExclusionList]
\$ntfs.log
\hiberfil.sys
\pagefile.sys
\swapfile.sys
"\System Volume Information"
\RECYCLER
\Windows\CSC

[CompressionExclusionList]
*.mp3
*.zip
*.cab
\WINDOWS\inf\*.pnf

如果将配置列表文件命名为wimscript.ini,并存储在DISM目录(DISM.exe 文件所在的目录)中,当使用/Capture-Image 选项(不论是否包括/Compress 参数)时,它将自动运行,而不需要使用 /ConfigFile 参数。
使用/ConfigFile 参数,可让你在使用DISM.exe捕获映像时为每个文件和文件夹自定义指定的压缩、捕获和边界对齐操作。可以使用文本编辑器创建配置列表 (.ini) 文件。比如,在D:\backup下有一个ExclusionList.ini,通过在初始备份命令最后面加上“ /ConfigFile:D:\backup\ExclusionList.ini”即可。

DNSPod动态IP解析更新程序

脚本是Python写的,树莓派上可直接运行。

替换上你的Email,密码,域名ID,记录ID等参数,就可以运行了。 会在后台一直运行,每隔30秒检查一遍IP,如果修改了就更新IP。
获得domain_id可以用

curl -k https://dnsapi.cn/Domain.List -d "login_email=xxx&login_password=xxx"

获得record_id类似

curl -k https://dnsapi.cn/Record.List -d "login_email=xxx&login_password=xxx&domain_id=xxx"

加入开机自动运行的方法:
编辑/etc/rc.local文件,在“exit 0”那一行前面加上一行

su root -c "python /home/pypod.py"

树莓派 motion安装摄像头实现远程监控

下面我们介绍如何来给树莓派装个USB摄像头,然后远程访问摄像头拍摄的即时画面。
首先你需要一个树莓派能兼容的USB摄像头,笔者用的是罗技(Logitech)C270 高清网络摄像头,插上即可。软件方面非常简单只需要一个软件:motion。
假设你的树莓派已经装好了 Raspbian 的系统,你只需要:

然后打开 motion daemon 守护进程,让他可以一直在后台运行:

修改motion的配置文件:

然后运行 motion:

现在我们的摄像头已经变成了一台网络摄像头。在chrome浏览器下访问 http://[your.domain]:8081 即可看到摄像头当前拍摄的画面。

C++内存泄露和检测

C++中的内存泄露一般指堆中的内存泄露。堆内存是我们手动malloc/realloc/new申请的,程序不会自动回收,需要调用free或delete手动释放,否则就会造成内存泄露。内存泄露其实还应该包括系统资料的泄露,比如socket连接等,使用完后也要释放。

内存泄露的原因:

总结下来,内存泄露大概有一下几个原因:

1、编码错误:malloc、realloc、new申请的内存在堆上,需要手动显示释放,调用free或delete。申请和释放必须成对出现malloc/realloc对应free,new对应delete。前者不会运行构造/析构函数,后者会。对于C++内置数据类型可能没差别,但是对于自己构造的类,可能在析构函数中释放系统资源或释放内存,所以要对应使用。

2、“无主”内存:申请内存后,指针指向内存的起始地址,若丢失或修改这个指针,那么申请的内存将丢失且没有释放。

3、异常分支导致资源未释放:程序正常执行没有问题,但是如果遇到异常,正常执行的顺序或分支会被打断,得不到执行。所以在异常处理的代码中,要确保系统资源的释放。

4、隐式内存泄露:程序运行中不断申请内存,但是直到程序结束才释放。有些服务器会申请大量内存作为缓存,或申请大量Socket资源作为连接池,这些资源一直占用直到程序退出。服务器运行起来一般持续几个月,不及时释放可能会导致内存耗尽。

5、类的析构函数为非虚函数:析构函数为虚函数,利用多态来调用指针指向对象的析构函数,而不是基类的析构函数。

内存泄露的检测

内存泄露的关键就是记录分配的内存和释放内存的操作,看看能不能匹配。跟踪每一块内存的声明周期,例如:每当申请一块内存后,把指向它的指针加入到List中,当释放时,再把对应的指针从List中删除,到程序最后检查List就可以知道有没有内存泄露了。Window平台下的Visual Studio调试器和C运行时(CRT)就是用这个原理来检测内存泄露。

在VS中使用时,需加上

#define _CRTDBG_MAP_ALLOC

#include <crtdbg.h>

crtdbg.h的作用是将malloc和free函数映射到它们的调试版本_malloc_dbg和_free_dbg,这两个函数将跟踪内存分配和释放(在Debug版本中有效)

_CrtDumpMemoryLeaks();

函数将显示当前内存泄露,也就是说程序运行到此行代码时的内存泄露,所有未销毁的对象都会报出内存泄露,因此要让这个函数尽量放到最后。

例如:

上述代码中,内存申请了两块,但是只释放了一块,运行调试,会在output窗口输出:

Dumping objects ->
{136} normal block at 0x00084D70, 50 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

可以看到会检测到内存泄露。 但是并没有检测到泄露内存申请的位置,已经加了宏定义#define _CRTDBG_MAP_ALLOC。原因是申请内存用的是new,而刚刚包含头文件和加宏定义是重载了malloc函数,并没有重载new操作符,所以要自己定义重载new操作符才能检测到泄露内存的申请位置。修改如下:

运行结果:

Detected memory leaks!
Dumping objects ->
e:\c++\test\内存泄露检测2\main.cpp(13) : {62} normal block at 0x001714F8, 50 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
e:\c++\test\内存泄露检测2\main.cpp(12) : {61} normal block at 0x00171458, 100 bytes long.
Data: <                > CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD CD
Object dump complete.

可以看到

main.cpp()括号里面的数字就是泄露内存的起始位置。那么后面的{62} normal block at 0x001714F8, 50 bytes long.
代表什么?

大括号{}里面的数字表示第几次申请内存操作;0x001714F8表示泄露内存的起始地址,CD CD表示泄露内存的内容。

为什么是第62次申请内存,因为在初始化操作时也申请了内存。通过这个信息,可以设置断点。调用long _CrtSetBreakAlloc(long nAllocID)可以再第nAllocID次申请内存是中断,在中断时获取的信息比在程序终止时获取的信息要多,你可以调试,查看变量状态,对函数调用调试分析,解决内存泄露。

block分为3中类型,此处为normal,表示普通,此外还有client表示客户端(专门用于MFC),CRT表示运行时(有CRT库来管理,一般不会泄露),free表示已经释放掉的块,igore表示要忽略的块。

在上面程序中,调用_CrtDumpMemoryLeaks()来检测内存泄露,如果程序可能在多个地方终止,必须在多个地方调用这个函数,这样比较麻烦,可以在程序起始位置调用_CrtSetDbgFlag ( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF ),这样无论程序何时终止,都会在终止前调用_CrtDumpMemoryLeaks()。

 

除此之外,还可以在某时刻设置检查点,获取当时内存状态的快照。比较不同时刻内存状态的差异。

输出结果为:

0 bytes in 0 Free Blocks.
100 bytes in 1 Normal Blocks.
8434 bytes in 54 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 8963 bytes.
Total allocations: 14003 bytes.
0 bytes in 0 Free Blocks.
150 bytes in 2 Normal Blocks.
8434 bytes in 54 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 8963 bytes.
Total allocations: 14053 bytes.
0 bytes in 0 Free Blocks.
50 bytes in 1 Normal Blocks.
0 bytes in 0 CRT Blocks.
0 bytes in 0 Ignore Blocks.
0 bytes in 0 Client Blocks.
Largest number used: 0 bytes.
Total allocations: 50 bytes.

也可以用此法更复杂检测内存泄露,例如设置检查点,检查检查点之间的内存泄露。