2023年9月

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的使用就已经倒在了安装的过程中。下的东西越多复杂程度越大出现问题的概率也会增加,这是让人诟病的。。