使用 DISM 处理 Windows 安装镜像
Windows 使用了 Wim 来压缩安装镜像,这个镜像中包含了展开到目标系统盘中的镜像。所以可以通过 DISM 脱机处理安装镜像。以下是一些常用的命令。还可以添加预安装的应用(UWP)和开始屏幕指定等等,这些可以参看引用1
- 展开镜像到目标目录
Dism /Mount-Image /ImageFile:wim文件 /index:目标的系统版本的索引 /MountDir:展开的目录
- 添加驱动程序
Dism /Image:展开的目录 /Add-Driver /Driver:驱动的目录或者inf文件 /Recurse
。注意使用了Recure
开关可以递归地将若干个驱动文件加入到展开的镜像中,但是这会增大 install.wim 的大小(包含不同的 inf 但是由共享相同的驱动文件) - 为镜像添加更新(仅 msu 和 cab 支持)
Dism /Image:展开的目录 /Add-Package /PackagePath:MSU或者CAB的路径
- 启用某种功能(以启用 .Net Framework 3.5 为例)
Dism /Image:展开的目录 /Enable-Feature /FeatureName:NetFx3 /ALL /Source:指定的组件目录(可以是光盘的 sources\sxs)
进行完所有的操作后,可以进行提交(commit)或放弃(discard)。如果需要提价请确保展开源 wim 文件还存在。例如:Dism /Unmount-Wim /MountDir:展开的目录 /Commit
就会将修改后的镜像更新到源 wim 文件对应的镜像位置(相应的索引)。
Linux 编译 CSAPP 用的 Y86-64 模拟器(GUI)
由于官网提供的 Y86-64 模拟器只能使用 Tcl/tk 8.5, 而最新的 Fedora 27 自带的是 Tcl 8.6,所以需要手动编译 Tcl 和 Tk。
- 编译 Tcl/Tk 8.5 最后一个 8.5 版本的Tcl 8.5.19 和 Tk 8.5.19。在使用 Makefile 编译之前需要安装 libX11-devel 和 libXpm-devel。然后
make
和make install
进行编译、安装。默认的目录在/usr/local
下,include
和lib
也在/usr
对应的目录下。 - 编译模拟器,安装 flex、flex-devel、bison 和 bison-devel,将下载的模拟器文件 sim.tar 解压,打开其中的 Makefile,修改一下的参数,指定对应的 Tcl/Tk 路径。
然后
make clean & make
编译。 - 检验 ,切换到 pipe 目录, 运行
./psim -t -g ../y86-code/asum.yo
。会出现如下的界面:
可能的错误:
./psim: error while loading shared libraries: libtk8.5.so: cannot open shared object file: No such file or directory
错误,那就是需要添加动态链接库的目录到/etc/ld.so.conf
中,例如:最后使用
ldconfig
生成缓存,检查是否有链接库的信息。
扩充:Windows 环境下编译
现在对网上的各种博客无感,很多文章要么是 N年前的内容或者是谬误。所有选哟自己动手实践!
虚拟 LINUX 环境
我是用的是 MSYS2,这个环境使用的 pacman 管理包,可以支持多语言。可以支持 MINGW32 和 MINGW64。在 Windows 情况下,使用的 Win32 的某些库文件所以生成的程序是 exe。另外,包管理可以避免去编译某些程序的依赖库(Y86 模拟器需要 flex 和 bison,而 GNU 只提供 Win32 版本,而编译器是64位的环境)。注意路径不要有空格
安装就不介绍了。需要设置下安装源:
- /etc/pacman.d/mirrorlist.mingw32 : 开头添加
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/i686
- /etc/pacman.d/mirrorlist.mingw64 : 开头添加
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/mingw/x86_64
- /etc/pacman.d/mirrorlist.msys : 开头添加
Server = https://mirrors.tuna.tsinghua.edu.cn/msys2/msys/$arch
- 使用命令
pacman -Sy
和pacman -Syu
刷新源和更新程序
接下来安装编译链工具、依赖库:pacman -S mingw-w64-x86_64-toolchain libraries development compression VCS sys-utils net-utils msys2-devel base-devel base
。可能会提示替换警告,可以继续。这样安装后,vim 可能无法使用了,先卸载(-R) git (vim 的依赖项),再重新安装。
修改文件
打开下载好的源码,找到 Makefile 文件,修改一下的内容。(网上传说不能用 tk8.6 及以上。其实 tk8.6 是可以的)
然后使用 make 命令编译程序。有几个注意:
C:/Programs/msys64/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/7.3.0/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lfl
: 修改 misc 下的 Makefile,指定 flex 库的路径:C:\Programs\msys64\tmp\ccv14H5r.o:ssim.c:(.data+0x0): undefined reference to matherr
: 找到提示的文件(这里是 ssim.c ),找到 matherr 的声明(一般是一个函数的声明),改为 _matherr。
然后运行(一定要在终端)之前提到的测试例子:
参考
编译 ffmpeg 以及解码器
编译各种解码器
- yasm 汇编工具 使用
yum install yasm-devel yasm
直接安装对应版本系统的二进制文件 - x264 这个是提供 H264 编码的库,下载源码。然后使用
./configure --prefix=/usr/local/ffmpeg --enable-shared --enable-static --enable-yasm
。在这里为了省事,直接把编译好的动态链接可以放入待会会安装的 ffmpeg 的目录中。注意一定要使用开启--enanble-shared
这个选项否则就会在 ffmpeg 编译的过程中发生链接错误(can not be used when making a shared object; recompile with -fPIC
)! - x265 下载1.9版本的 h265 源码 注意 x265 使用的 cmake 所以需要安装好 cmake。进入目录
build/linux
运行PATH="/usr/local/bin:$PATH" cmake -G "Unix Makefiles" -DCMAKE_INSTALL_PREFIX="/usr/local/ffmpeg" -DENABLE_SHARED:bool=off ../../source
就可以编译好动态链接库版本的 x265 编码器。 - libvpx 这个提供 WebM 的编码器,下载源码 然后进入目录,
PATH="/usr/local/bin:$PATH" ./configure --prefix="/usr/local/ffmpeg" --disable-examples --disable-unit-tests
进行编译和安装。 - fdk-acc ACC 编码,下载源码, 不要使用 0.1.4 的版本。首先安装
automake, automake-devel 和 libtool
。然后运行autoreconf -fiv;./configure --prefix="/usr/local/ffmpeg" --enable-shared
。 - 这些编码仅仅是用来处理视频的,声音还要另外安装。这里就不多说了。现在编译 ffmpeg。。configure 使用如下的一些参数:
--enable-gpl
:使用 GPL 协议;--pkg-config-flags
: pkgconfig(Makefile 的一个帮助工具,用于保存第三方引用链接的信息);--enable-xxx
:编译 xxx 编码器。总的来说就是./configure --prefix=/usr/local/ffmpeg --pkg-config-flags="--static" --enable-shared --enable-yasm --enable-libx264 --enable-gpl --enable-pthreads --bindir="/usr/local/bin" --enable-libfdk-aac --enable-libvpx --enable-libx264 --enable-libx265 --enable-nonfree
。为了编译为动态链接库的版本,还需要使用make CFLAGS='-fPIC'
。最后安装即可,生成的可执行文件在/usr/bin
下(--bindir 指定)。
注意事项
- 编译 ffmpeg 的时候找不到 x265 的 pkgconfig ,则需要因把
/usr/local/ffmpeg/lib/pkgconfig
添加到变量 PKG_CONFIG_PATH 中,例如:/usr/local/x264/lib/pkgconfig:/usr/local/ffmpeg/lib/pkgconfig:/usr/lib64/pkgconfig
,然后 export 到 shell 中。 - 找不到链接库,同上一篇文章,把
/usr/local/ffmpeg/lib
添加到 ld.so.conf 中,然后 sudo ldconfig。 - 编译的时候找不到头文件:(有 x264 是因为之前 x264 并没有编译到 ffmpeg 中)
C_INCLUDE_PATH=$C_INCLUDE_PATH:/usr/local/ffmpeg/include:/usr/local/x264/include CPLUS_INCLUDE_PATH=$CPLUS_INCLUDE_PATH:/usr/local/ffmpeg/include:/usr/local/x264/include export C_INCLUDE_PATH export CPLUS_INCLUDE_PATH LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/local/x264/lib:/usr/local/ffmpeg/lib export LD_LIBRARY_PATH
题外话:虚拟机中的 ffmpeg 输出流到实体机
在 Linux 下可以借助 ffserver 响应用户的请求。
为了能够使主机与虚拟机相互 ping 通,可以使用虚拟机的桥接模式将虚拟机和主机放置在一个子网之中。
将虚拟机与主机放置在一个子网中:
- 添加一个环回网卡。在计算机管理MMC中,点击操作然后添加红框中的网络适配器设备
- 管理员打开 VMware 的虚拟网络编辑器(这是一个例子),找到 VMnet 0,在桥接模式的下拉列表中选择刚刚那个网卡并确定。
- 打开那个网卡的 IPv4 的设置,输入一个指定的主机 IP地址、网关和子网掩码:
- 这样主机的 IP 地址为 192.168.100.101,网关是 192.168.100.100(用来指定将数据发送到那个网卡上)。同样需要设置虚拟机的 IP 地址,保持子网掩码和网关与主机一直,IP 地址只要在 192.168.100. 子网内就可以了:
- 主机和虚拟机的 IP 分别为 192.168.100.101 和 192.168.100.102。但是如果需要访问各自的服务,一个不好的方法是关闭二者都有的防火墙。Fedora:
systemctl stop firewalld.service systemctl disable firewalld.service
这样就可以 ping 通:
搭建 ffserver
ffserver 默认的配置文件在 /etc/ffserver.conf
,通过开关 -f 也可以指定其他的。ffserver 需要:
- 绑定一个监听的端口这样可以监听远程的访问
- 添加一个输出配置,用于指定广播流的格式
- 指定本地由 ffmepg 传送到的 ffm 的定义以及关联的(feed)输出配置
/etc/ffserver.conf
:
HTTPPort 8090 # Port to bind the server to HTTPBindAddress 0.0.0.0 MaxHTTPConnections 2000 MaxClients 1000 MaxBandwidth 10000 # Maximum bandwidth per client # set this high enough to exceed stream bitrate CustomLog - NoDaemon # Remove this if you want FFserver to daemonize after start <Feed feed1.ffm> # This is the input feed where FFmpeg will send File /tmp/feed1.ffm # video stream. FileMaxSize 64M # Maximum file size for buffering video ACL allow 127.0.0.1 # Allowed IPs </Feed> <Stream test.webm> # Output stream URL definition Feed feed1.ffm # Feed from which to receive video Format webm # Audio settings #AudioCodec vorbis #AudioBitRate 64 # Audio bitrate # Video settings VideoCodec libvpx VideoSize 320x240 # Video resolution VideoFrameRate 30 # Video FPS AVOptionVideo flags +global_header # Parameters passed to encoder # (same as ffmpeg command-line parameters) AVOptionVideo cpu-used 0 AVOptionVideo qmin 10 AVOptionVideo qmax 42 AVOptionVideo quality good NoAudio #PreRoll 15 #StartSendOnKey VideoBitRate 128 # Video bitrate </Stream> <Stream status.html> # Server status URL Format status # Only allow local people to get the status ACL allow localhost ACL allow 192.168.0.0 192.168.255.255 </Stream> <Redirect index.html> # Just an URL redirect for index # Redirect index.html to the appropriate site URL http://www.ffmpeg.org/ </Redirect>
由于不需要传输声音所以我没有指定声音的编码。定义了一下的信息
- 客户通过:http://ip:8090/status.html 可以获得当前 ffserver 的运行信息
- 输入源输出到本地的广播源:http://127.0.0.1/feed1.ffm
- 客户可以通过:http://ip:8090/test.webm 访问这个流。
ffmpeg 命令行输出到广播源
- 输出一段视频:
ffmpeg -i ~/ai.mp4 -r 30 http://127.0.0.1:8090/feed1.ffm
- 输出摄像头(虚拟机不能使用):
ffmpeg -f video4linux2 -s 320x240 -r 30 -i /dev/video0 http://127.0.0.1:8090/feed1.ffm
使用 ffmpeg 对流进行处理
- 保存为本地的视频文件:
ffmpeg -i http://192.168.100.102:8090/test.webm save.mp4
内网穿透
因为最近在学校的服务器上开启了一个虚拟机,但是虚拟机的网络是处于在学校的内网之中。而寝室的宽带网络独立于学校的内网,所以需要使用内网穿透绕过路由将某些端口暴露到外网中。
服务端配置
- 一个已经备案的域名:
- 服务端运行
sudo apt-get install build-essential golang mercurial git
,应为 ngrok 是基于 Go 语言开发,可以直接生成机器码也可以跨平台地编译不同系统的版本。 - 用于 ngrok 在编译的时候需要很多其他的源,所以需要下载其他人修改后的版本
git clone https://github.com/tutumcloud/ngrok.git ngrok
,然后进入目录 ngrok。导出指定的域名:export NGROK_DOMAIN="ddayzzz.wang"
- 由于我们的域名已经备案了,所以在编译的时候只需要指定证书和密钥就可以(我的域名是 Let's Encrypt,所以证书的、密钥目录在
/etc/letsencrypt/live/ddayzzz.wang
):
cp /etc/letsencrypt/live/ddayzzz.wang/cert.pem assets/client/tls/ngrokroot.crt # 复制服务器证书,用于编译 cp /etc/letsencrypt/live/ddayzzz.wang/cert.pem cert.crt # 复制服务器证书,这个用于运行 cp /etc/letsencrypt/live/ddayzzz.wang/privkey1.pem privkey.pem # 复制私钥证书
- 指定了证书之后,以后 ngrok 都会按照证书进行数据的加密。使用
sudo make release-server release-client
编译 Linux 服务端和客户端。 - 编译后会在 bin 目录下生成服务端 ngrokd 和客户端 ngrok。运行服务端:
./bin/ngrokd -tlsKey="privkey.pem" -tlsCrt="cert.pem" -domain="$NGROK_DOMAIN" -httpAddr=":8000" -httpsAddr=":8001" -tunnelAddr=":4443"
。
参数 | 含义 |
---|---|
tlsCrt | 服务器证书 |
tlsKey | 私钥证书 |
httpAddr | http转发的端口号 |
httpsAddr | https 转发的端口号 |
tunnelAddr | ngrok 客户端连接的管理用途的端口 |
- 注意,有些虚拟主机提供商会限制端口入方向,所以需要关闭端口的限制。
如果没有问题了,可以输入一些测试 https://ddayzzz.wang:8001
,如果出现:就正常。
客户端配置
注意,由于ngrok 2.x 是闭源的所以,不要使用最新的而是使用 1.7 的版本。创建配置文件(ngrok 使用 yaml 配置文件格式,需要使用空格而不是制表来控制缩进):
server_addr: "ddayzzz.wang:4443" trust_host_root_certs: true tunnels: rmdp: remote_port: 8003 proto: tcp: "3389"
这里转发了远程桌面服务,也就是我通过外网的域名的端口 8003 就可以访问内网的客户端上的 3389 端口了。注意要指定 trust_host_root_certs
让 ngrok 客户端信任其他认证机构签发的证书。否则服务端会提示 bad:certification,客户端一直 reconnecting。
运行截图:
服务端持久运行
- 在后台一直运行:
apt install screen screen keepngrok # 随便一个名字 # 运行了一个子 shell 环境 # 输入并运行之前的服务器启动命令 ... # Ctrl+A+D 可以放到后台运行。 # 直接退出 shell
问题
- 只能转发一个端口,如果需要做多端口转发就可以使用 VPN 转发。
- FTP 服务即使转发了21端口也不能访问内网的 ftp 服务。
参考
- (CSDN) ngrok 后台运行的方法
- (imququ.com)搭建 ngrok 服务实现内网穿透
- (Github)self-hosted ngrokd - client fails with 'Certificate signed by unknown authority' on Mac OS X
- (ubock.com)CentOS 7 搭建ngrok服务器
引用&参考
- DISM 的使用
- (CSDN)CSAPP Y86 环境部署
- (Cnblogs) Linux找不到动态链接库
- (ffserver wiki)ffserver 文档
- (Cnblogs)Linux 下 WebM 直播搭建
- (CSDN)ffmpeg+ffserver搭建流媒体服务器
- (Linuxidc) Fedora 18/19 以上关闭防火墙
- (baidu) 构建虚拟机PC连接
- (CSDN) linux 下编译 x256
- (Cnblogs) linux 下 找不到 pkgconfig 路径
- (Cnblogs) linux下编译支持librtmp、libx264、libfaac的ffmpeg
- (Cnblogs)Linux---centos编译安装ffmpeg
- (Cnblogs) Compile with fpic
- (CSDN) PKG_CONFIG_PATH 路径设置
- (内存溢出)CentOS编译安装ffmpeg以及相关编码解码器
- (Chinaunix)Linux添加头文件路径—INCLUDE_PATH
他
2019年1月21日
学学方兄搞个打赏按钮吧,我想打赏但是找不到二维🐎
shu
2019年1月21日
你啊 naive, 个人网站一律不得经商!
shu
2019年8月21日
吼啊! 😯