levels 发布的文章

stat结构体如下:

struct stat:
dev_t        st_dev        /*id device containing file*/
ino_t        st_ino        /*inode number*/
mode_t        st_mdoe        /*protection*/
nlink_t        st_nlink    /*number of hard link*/
uid_t        st_uid        /*user id of owner*/
gid_t        st_gid        /*group id of owner*/
dev_t        st_rdev        /*device ID(if specical file)*/
off_t        st_size        /*total size in bytes*/
blksize_t    st_blksize    /*blocksize for filesystem I/O*/
blkcnt_t    st_blokcs    /*number of blocks allocated*/
time_t        st_atime    /*time to last access*/
time_t        st_mtime    /*time to last modification*/
time_t        st_ctime    /*time to last satus change*/

struct stat常用字段:

st_mode:文件的访问权限和文件类型。您可以使用宏(如 S_ISREG()、S_ISDIR())来检查文件类型和权限。
st_size:文件的大小(以字节为单位)。
st_uid:文件所有者的用户ID。
st_gid:文件所属组的组ID。
st_atime:最后访问时间(上次读取文件的时间)。
st_mtime:最后修改时间(上次修改文件的时间)。
st_ctime:文件状态改变时间(上次修改文件权限、所有者等的时间)。

自定义命令的显示写法(开源项目里命令使用提示类似linux那种自带提示):

if(argc != 2){printf("Usage : stat <pathname>\n");exit(-1);}

argc处的2可以为任意num,判断的是用户输入的参数是否数量对应,不对应就显示Usage提示并退出

实例

综上,可以写出类ls命令的自定义stat命令实例,代码如下:

#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<sys/types.h>
#include<unistd.h>

int main(int argc,char ** argv)
{
  struct stat buf;
  
  if(argc != 2){
  printf("Usage : stat <pathname>\n");exit(-1);
    }
  if(stat(argv[1],&buf) != 0){
  printf("stat error!\n");exit(-1);
 }
  printf("#DEV_ID       :\n",(int)buf.st_dev);
  printf("#i-node       :\n",(int)buf.st_ino);
  printf("#link         :\n",(long)buf.st_nlink);
  printf("#UID          :\n",(int)buf.st_uid);
  printf("#GID          :\n",(int)buf.st_gid);
  printf("#size         :\n",(long)buf.st_size);
  printf("#modify_time  :\n",(long)buf.st_mtime);
  printf("#change_time  :\n",(long)buf.st_ctime);
  exit(0);
    }

在linux项目中,源码的编译一般分为手动和自动,两种方法都是基于gcc实现的。但在修改和重新编译的便捷程度上来说,手动不如自动,而自动编译一般是基于makefile来实现的编译。

makefile尤其是在中大型C Project中是非常有用的,实现了代码修改和编译的解耦合。实例如下:

code.c

//code.c
#include "code.h"
int myfun(int in){
  return in + 1;
}

code.h

//code.h
extern int myfun(int);

prog.c

//prog.c
#include<stdio.h>
#include "code.h"
int main(void){
  int i = 1;
  printf("myfun(i) = %d\n",myfun(i));
}

如上实例其实比较简单,手动编译的话其实也只需要三行命令实现,如下:

gcc -c code.c -o code.o
gcc -c prog.c -o prog.o
gcc prog.o code.o -o test

但是如果我们通过makefile,其实可以只通过更为简短好记的命令完成编译:

Makefile

test: prog.o code.o
    gcc prog.o code.o -o test
    ./test
prog.o: prog.c code.h
    gcc -c prog.c -o prog.o
code.o: code.c code.h
    gcc -c code.c -o code.o
clean:
    rm -f *.o test

命令:

make test    //实现编译并运行
make clearn    //清除中间文件和编译后的可执行文件

通过比较手动和自动,不难发现基于makefile的自动编译省去了敲命令的时间,还减少了gcc命令的输入错误和输入时间,有助于后期项目的修改和维护。

详解Makefile文件逻辑

makefile的撰写逻辑其实是非常清晰的,想象有一颗倒过来的树,树的顶端就是你最终想要实现的可运行的文件,而依次往下就是你要编译的文件,得到的图解就会如下图所示:(基于上面的实例做示范)

make工作树
借助工作树,可以帮助你更好的理解项目的依赖和编译过程.与此同时它也可以辅助你快速的写出项目的makefile文件实现项目的自动编译。

通过上面的工作树,我们可以得知:makefile里每一次编译动作的执行都需要两个参数(clean动作除外),如:
test: prog.o code.o
对此再进一步总结,就可以得出格式如下:

目标文件:    依赖文件列表
TAB命令
...
TAB命令
...

拓展

以上只是最简单和最基础的makefile的使用,进阶可以参考:
Makefile入门(超详细一文读懂)
全网最牛Linux内核Makefile文件详解

打开ensp模拟器,点击新建拓扑

选择本次实验需要的两样设备:交换机和pc机
S3700型号交换机
PC机

连接线选择直通线(Copper) (如果不清楚设备线的选用可以用auto自动选择连接线)
连接线的选取

完成上述操作后的拓扑图应该如下图这样:
完成后拓扑图
然后启动所有设备:
设备的启动
在模拟器右侧可以看到设备的对应端口以及启用状态(侧边状态显示按ctrl+r后展示出来)
启动前状态
启动后状态

配置pc常规参数(主机名称,IP地址,子网掩码以及网关)
pc配置
pc配置

进行主机正常通信的测试:
通信测试

对ICMP数据包进行抓包:
因为抓包功能是依托于wireshark实现的,需要一定的时间进行wireshark的启动等待
请输入图片描述
请输入图片描述
请输入图片描述
请输入图片描述

实验配置到此已经成功完成,实现了主机间的通信并通过wireshark对ICMP包进行了抓取查看。

个人的碎碎念

就我个人想法来说,华为的ensp要用到物理机的许多权限是因为它想要实现更加真实的模拟环境,但是对于没有学过模拟器或是习惯思科逻辑的人来说,很多地方是有些过于繁琐和难以操作的。官方文档的书写不规范有省略,增大了ensp安装和学习的难度曲线。许多人可能还没到真正学习ensp的使用就已经倒在了安装的过程中。下的东西越多复杂程度越大出现问题的概率也会增加,这是让人诟病的。。

音视频混流:(音频优先考虑转换成mp3格式的)
ffmpeg -i xxx1.mp3 -i xxx2.mp4 out.mp4

转码视频格式:
ffmpeg -i input.mp4 -c:v libx264 -c:a aac output.mp4
将输入视频文件 input.mp4 转码为 H.264 视频编解码器和 AAC 音频编解码器的 MP4 格式文件 output.mp4。

裁剪视频:
ffmpeg -i input.mp4 -vf "crop=640:480:10:10" output.mp4
将输入视频文件 input.mp4 裁剪为 640x480 分辨率,起始位置为 (10, 10),然后输出为 output.mp4。

剪切视频:
ffmpeg -i input.mp4 -ss 00:01:00 -t 00:00:30 -c:v copy -c:a copy output.mp4
从输入视频文件 input.mp4 中剪切出从第 1 分钟开始,时长为 30 秒的视频,并保持原始编解码方式,然后输出为 output.mp4。

提取音频:
ffmpeg -i input.mp4 -vn -c:a copy output.aac
从输入视频文件 input.mp4 中提取音频并保存为 AAC 格式文件 output.aac。

合并多个视频:
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "0:vconcat=n=2:v=1:a=0" output.mp4
将 input1.mp4 和 input2.mp4 两个视频合并为一个输出视频 output.mp4。

视频录制:(时代感的画质,不可见的录制时间,无法确定的录制效果,仅可用来学习掌握ffmpeg使用,日常录制还是优先主流市面上的软件)
ffmpeg.exe -f gdigrab -i desktop out.mp4
ffmpeg.exe -f gdigrab -framerate 6 -i desktop out.mp4
ffmpeg.exe -f gdigrab -framerate 6 -offset_x 50 -offset_y 50 -video_size 400x400 -i title=ffmpeg out.mp4

视频画中画:
ffmpeg -re -i input.mp4 -vf "movie=sub.mp4,scale=480x320[test]; in overlay [out]" -vcodec libx264 output.flv(1260X740为居中的位置)

视频画中画(坐标设置):overlay处的x,y坐标数值越大位置越居中
ffmpeg -re -i input.mp4 -vf "movie=sub.mp4,scale=480x320[test]; in overlay=x=main_w-480:y=main_h-320 [out]" -vcodec libx264 output.flv

转换音频采样率:
ffmpeg -i input.wav -ar 44100 output.wav
将输入音频文件 input.wav 的采样率转换为 44100 Hz,并输出为 output.wav。

定时视频截图:
ffmpeg -i input.flv -ss 00:00:7.435 -vframes 1 out.png

添加水印:
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4
将 watermark.png 图片添加到 input.mp4 视频的左上角,然后输出为 output.mp4。

调整视频大小:
ffmpeg -i input.mp4 -vf "scale=1280:720" output.mp4
将输入视频文件 input.mp4 调整为 1280x720 分辨率,然后输出为 output.mp4。

提取视频:
ffmpeg -i input.mp4 -an -c:v copy output.mp4
从输入视频文件 input.mp4 中提取视频部分(去除音频),并保持原始视频编解码方式,然后输出为 output.mp4。

调整帧率:
ffmpeg -i input.mp4 -r 30 output.mp4
将输入视频文件 input.mp4 的帧率调整为 30 帧/秒,并输出为 output.mp4。

添加字幕:
ffmpeg -i input.mp4 -vf "subtitles=sub.srt" output.mp4
将名为 sub.srt 的字幕文件添加到 input.mp4 视频中,并输出为 output.mp4。

调整音量:
ffmpeg -i input.mp3 -af "volume=2.0" output.mp3
将输入音频文件 input.mp3 的音量调整为原来的两倍,并输出为 output.mp3。

音频半速处理:
ffmpeg -i input.wav -filter_complex "atempo=tempo=0.5" -acodec aac output.aac

音频2倍速处理:
ffmpeg -i input.wav -filter_complex "atempo=tempo=2.0" -acodec aac output.aac

视频半速处理:
ffmpeg -re -i input.mp4 -filter_complex "setpts=PTS*2" output.mp4

视频2倍速处理:
ffmpeg -i input.mp4 -filter_complex "setpts=PTS/2" output.mp4

视频旋转:
ffmpeg -i input.mp4 -vf "transpose=1" output.mp4
将输入视频文件 input.mp4 顺时针旋转 90 度,并输出为 output.mp4。

视频片段拼接:
ffmpeg -f concat -i filelist.txt -c copy output.mp4
通过使用一个包含视频文件列表的 filelist.txt 文件,将多个视频片段拼接成一个输出视频 output.mp4。

调整视频亮度、对比度和饱和度:
ffmpeg -i input.mp4 -vf "eq=brightness=0.2:contrast=1.5:saturation=1.5" output.mp4
通过视频滤镜来调整输入视频文件 input.mp4 的亮度、对比度和饱和度,并输出为 output.mp4。

创建 GIF 动画:
ffmpeg -i input.mp4 -vf "fps=10,scale=320:-1:flags=lanczos" -c:v gif output.gif
将输入视频文件 input.mp4 转换为 GIF 动画文件 output.gif,并设置帧率为 10 帧/秒,缩放到宽度 320 像素。

视频加速或减速:
ffmpeg -i input.mp4 -vf "setpts=0.5*PTS" output.mp4
将输入视频文件 input.mp4 加速为原来的一半速度,并输出为 output.mp4。

视频反转:
ffmpeg -i input.mp4 -vf "reverse" output.mp4
将输入视频文件 input.mp4 反转,即播放顺序颠倒,然后输出为 output.mp4。

提取视频帧为图像:
ffmpeg -i input.mp4 -vf "select='eq(pict_type\,I)'" -vsync vfr frame%d.png
从输入视频文件 input.mp4 中提取关键帧(I 帧)作为图像,并以帧号命名输出的图像文件。

音频混流:
ffmpeg -i input1.mp3 -i input2.mp3 -filter_complex "0:aamix=inputs=2:duration=first:dropout_transition=2" output.mp3
将两个音频文件 input1.mp3 和 input2.mp3 进行混流,输出一个包含两者的混合音频文件 output.mp3。

视频加水印并指定位置:
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" output.mp4
将 watermark.png 图片添加到 input.mp4 视频的左上角,指定水印位置为 (10, 10),然后输出为 output.mp4。

音频格式转换:
ffmpeg -i input.wav -c:a mp3 -b:a 192k output.mp3
将输入音频文件 input.wav 转换为 MP3 格式,并指定音频比特率为 192 Kbps,输出为 output.mp3。

裁剪视频段并添加转场效果:
ffmpeg -i input.mp4 -vf "crop=640:480:10:10" -t 5 -vf "fade=out:st=4:d=1" output.mp4
将 input.mp4 视频裁剪为 640x480 分辨率,起始位置为 (10, 10),然后在视频结束前添加一个 1 秒的淡出效果,总时长为 5 秒,输出为 output.mp4。

从视频中提取音频轨道:
ffmpeg -i input.mp4 -map a -c:a copy output.m4a
从 input.mp4 视频中提取音频轨道,保持原始音频编解码方式,输出为 output.m4a。

剪切和连接音频:
ffmpeg -i input.mp3 -ss 00:00:30 -t 00:01:30 -c:a copy part1.mp3
ffmpeg -i input.mp3 -ss 00:02:30 -t 00:01:00 -c:a copy part2.mp3
ffmpeg -i "concat:part1.mp3|part2.mp3" -c:a aac -strict experimental output.mp3
先从 input.mp3 音频中剪切出两部分音频,然后使用 concat 过滤器将它们连接起来,并输出为 output.mp3。

模糊淡入淡出效果:
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v]fade=out:st=3:d=1[v0];[1:v]fade=in:st=0:d=1[v1];[v0]boxblur=5:1:cr=0:ar=0[bg];[v1]boxblur=5:1:cr=0:ar=0[fg];bgoverlay=(W-w)/2:(H-h)/2[outv]" -map "[outv]" output.mp4
将 input1.mp4 和 input2.mp4 视频分别进行淡出和淡入,并在过渡期间模糊处理,然后叠加在一起,创建一个模糊淡入淡出效果。

溶解效果:
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v]fade=out:st=3:d=1[v0];[1:v]fade=in:st=0:d=1[v1];v0dissolve=transition=allslide[outv]" -map "[outv]" output.mp4
将 input1.mp4 和 input2.mp4 视频分别进行淡出和淡入,并使用溶解过渡效果,在过渡期间将两个视频混合在一起。

闪白效果:
ffmpeg -i input1.mp4 -i input2.mp4 -filter_complex "[0:v]fade=out:st=3:d=1[v0];[1:v]fade=in:st=0:d=1[v1];v0gltransition=duration=1:source=1:offset=pi[outv]" -map "[outv]" output.mp4
将 input1.mp4 和 input2.mp4 视频分别进行淡出和淡入,并使用闪白过渡效果,在过渡期间将两个视频混合在一起。