在现代软件开发项目中,要成为一个有效的软件开发人员,我们必须能够与其他项目贡献者并行进行开发。
源代码管理(SCM)系统不是什么新思想。为了编写一些能够更快速、简单地开发以后软件项目的软件,已经进行了很多尝试。
最新的源代码解决方案都包含了版本控制系统,它可以对源代码的修改进行回滚,从而将有害的代码剔除出项目之外,或者简单地跟踪哪些人修改了代码的哪些行的内容。版本控制系统试图解决开发人员在试图同时对某个文件进行修改时所出现的冲突问题,可以防止用户覆盖其他人所作的修改。源代码管理使用的很多流行解决方案都试图解决以前 SCM 解决方案中的失效问题。
集中化的版本控制系统通常采用两种方式:
流行的版本控制系统包括:
非常简单地说,Git 是 Linus Torvalds 最近实现的源代码管理软件。正如所提供的文档中说的一样,“Git 是一个快速、可扩展的分布式版本控制系统,它具有极为丰富的命令集,对内部系统提供了高级操作和完全访问。”
Torvalds 开始着手开发 Git 是为了作为一种过渡方案来替代 BitKeeper,后者之前一直是 Linux 内核开发人员在全球使用的主要源代码工具。开放源码社区中的有些人觉得 BitKeeper 的许可证并不适合开放源码社区的工作,因此 Torvalds 决定着手研究许可证更为灵活的版本控制系统。尽管最初 Git 的开发是为了辅助 Linux 内核开发的过程,但是我们已经发现在很多其他自由软件项目中也使用了 Git。例如,X.org 最近就迁移到 Git 上来了,很多 Freedesktop.org 的项目也迁移到了 Git 上。
Git 目前主要由寻找 CVS 或专有代码管理解决方案替代物的软件开发人员所使用。Git 与 CVS 有很多区别:
源码的版本管理
源码的提交管理
在核心上,开发模式受到现有模型的极大启发。中央回购拥有两个主要的分支,无限生命:
我们认为origin/master是源代码HEAD总是反映生产就绪状态的主要分支 。
我们认为origin/develop是主要的分支,源代码 HEAD总是反映出下一个版本的最新交付发展变化的状态。有人会称之为“整合分支”。这是每个自动夜间建造的地方。
当develop分支中的源代码达到稳定点并准备释放时,所有这些更改都应该以master 某种方式合并,然后用发布号标记。将详细讨论如何做到这一点。
因此,每次将更改合并到一起时master,根据定义,这是一个新的生产版本。我们往往对此非常严格,所以理论上,我们可以使用Git钩子脚本在每次提交时自动构建和推出我们的软件到我们的生产服务器 master。
pcap是一种数据流格式,wireshark软件可以直接把网络数据流变成这种格式。
在Linux里,pcap可以说是一种通用的数据流格式,很多开源的项目都需要用到这种格式的文件。
一般通过tcpdump或者 wireshark工具获取pcap文件。
使用tcpdump命令获取pcap文件
tcpdump基本用法 tcpdump [ -i interface ] [ -w file ] [ expression ]
Panda.Guo@2018-07-26 20:56:13 $ sudo tcpdump -i wlp2s0 -w ~/wl.pcap -vv
tcpdump: listening on wlp2s0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C69 packets captured
69 packets received by filter
0 packets dropped by kernel
Panda.Guo@2018-07-26 20:56:51 $
通过Ctrl+c
随时选择终止。
使用wireshark工具抓取pcap文件
上图是pcap的格式结构图,分成两大部分:
Global Header (共 24 Byte)整个数据流文件,只会有一个 Global Header,它定义了本文件的读取规则、最大储存长度限制等内容;
Packet Header(共 16 Byte) Packet Header可以有多个,每个Packet Header后面会跟着一串Packet Data,Packet Header定义了Packet Data的长度、时间戳等信息。
Caplen: 数据包长度:32位 ,标识所抓获的数据包保存在pcap文件中的实际长度,以字节为单位。
Len:数据包实际长度: 所抓获的数据包的真实长度,如果文件中保存不是完整的数据包,那么这个值可能要比前面的数据包长度的值大。
Packet Data(共 Caplen Byte)在包头之后,就是数据包的数据了,数据长度就是Caplen个Byte,
Panda.Guo@2018-06-26 20:01:00 $ hd ~/wl.pcap | less
00000000 d4 c3 b2 a1 02 00 04 00 00 00 00 00 00 00 00 00 |................|
00000010 00 00 04 00 01 00 00 00 08 d9 28 5a 85 ba 0b 00 |..........(Z....|
00000020 3c 00 00 00 3c 00 00 00 50 9a 4c 20 65 dc dc fe |<...<...P.L e...|
00000030 18 2a d5 c9 08 00 45 00 00 28 13 de 40 00 75 06 |.*....E..([email protected].|
00000040 7b f6 ca 59 e9 64 c0 a8 01 95 01 bb 15 bd 47 26 |{..Y.d........G&|
00000050 64 57 1b f9 dd fc 50 10 03 fe 78 ef 00 00 00 00 |dW....P...x.....|
00000060 01 95 01 bb 08 d9 28 5a 85 ba 0b 00 4b 01 00 00 |......(Z....K...|
00000070 4b 01 00 00 50 9a 4c 20 65 dc dc fe 18 2a d5 c9 |K...P.L e....*..|
00000080 08 00 45 00 01 3d 13 df 40 00 75 06 7a e0 ca 59 |[email protected]|
00000090 e9 64 c0 a8 01 95 01 bb 15 bd 47 26 64 57 1b f9 |.d........G&dW..|
000000a0 dd fc 50 18 03 fe 98 00 00 00 17 03 02 01 10 3c |..P............<|
000000b0 c4 c4 aa 39 d0 30 29 66 3e e5 2d 2d 39 60 64 ed |...9.0)f>.--9`d.|
.....
示例代码如下:
函数名称:pcap_t *pcap_open_offline(char *fname, char *ebuf)
函数功能:打开以前保存捕获数据包的文件,用于读取。
参数说明:fname参数指定打开的文件名。该文件中的数据格式与tcpdump和tcpslice兼容。”-“为标准输入。ebuf参数则仅在pcap_open_offline()函数出错返回NULL时用于传递错误消息。
函数名称:int pcap_loop(pcap_t *p, int cnt,pcap_handler callback, u_char *user)
函数功能: 捕获并处理数据包。此函数在cnt个数据包被处理或出现错误时才返回,但读取超时不会返回。。cnt参数为负值时pcap_loop()函数将始终循环运行,除非出现错误。
函数名称:void pcap_close(pcap_t *p)
函数功能:关闭p参数相应的文件,并释放资源。
对于 pcap_loop:
pcap_loop原型是pcap_loop(pcap_t *p,int cnt,pcap_handler callback,u_char *user)
其中第一个参数是pcap_open_offline返回的句柄,
第二个是指定捕获的数据包个数,如果为-1则无限循环捕获。
第四个参数user是留给用户使用的。
第三个是回调函数其原型如下:
pcap_callback(u_char* argument,const struct pcap_pkthdr* packet_header,const u_char* packet_content)
其中参数pcap_content表示的捕获到的数据包的内容
参数argument是从函数pcap_loop()传递过来的。注意:这里的参数就是指 pcap_loop中的 *user 参数
参数pcap_pkthdr 表示捕获到的数据包基本信息,包括时间,长度等信息.
另外:回调函数必须是全局函数或静态函数,其参数默认,比如pcap_loop()可以写成
pcap_loop(pcap_handle,10,pcap_callback,NULL)不能往里面传递实参.
pcap_loop和callback之间参数存在联系:
pcap_loop的最后一个参数user是留给用户使用的,当callback被调用的时候这个值会传递给callback的第一个参数(也叫user),
callback的最后一个参数p指向一块内存空间,这个空间中存放的就是pcap_loop抓到的数据包。
callback的第二个参数是一个结构体指针,该结构体定义如下:
// /usr/include/pcap/pcap.h
struct pcap_pkthdr {
struct timeval ts; /* 时间戳 */
bpf_u_int32 caplen; /* 已捕获部分的长度 */
bpf_u_int32 len; /* 该包的脱机长度 */
};
这个结构体是由pcap_loop自己填充的,用来取得一些关于数据包的信息
所以,在callback函数当中只有第一个user指针是可以留给用户使用的,如果你想给callback传递自己参数,那就只能通过pcap_loop的最后一个参数user来实现了