2017年1月

linux编程学习 01 linux IO 系统调用

一、文件I/O系统调用简介

1、标准库函数

遵守ISO标准,基于流的I/O,对文件指针(FILE结构体)进行操作

2、系统调用

兼容POSIX标准,基于文件描述符的I/O,对文件描述符进行操作,包括:
open(): 打开文件
create():创建文件
close(): 关闭文件
read(): 读取文件
write(): 写入文件
lseek(): 文件定位
这些不带缓存的函数都是内核提供的系统调用。它们不是ANSI C的组成部分,但是POSIX的组成部分。

二、文件描述符

1、对于内核而言,所有打开文件都由文件描述符引用。文件描述符是一个非负整数。当打开一个现存文件或创建一个新文件时,内核向进程返回一个文件描述符。当读、写一个文件时,用open或creat返回的文件描述符标识该文件,将其作为参数传送给read或write。
2、在POSIX应用程序中,整数0、1、2被替换成符号常数 STDIN_FILENO、STDOUT_FILENO和STDERR_FILENO。这些常数都定义在头文件 中。
3、文件描述符的范围是0-OPEN_MAX,早期的unix版本是19(允许每个进程打开20个文件),现在很多系统设置成23,linux为1024

标准文件指针

  • stdin 0
  • stdout 1
  • stderr 2

fdopen()

FILE *fdopen(int fd,const char* mode);

文件描述符 -----> 文件指针 (fd -----> FILE*)

fileno

int fileno(FILE *stream)

文件指针 -----> 文件描述符 (FILE* -----> fd)

三,函数介绍

一、open函数

1、 头文件(后面都是这个格式)

#include <sys/types.h>.        // 提供mode_t类型
#include <sys/stat.h>          // 提供open()函数的符号
#include <fcntl.h>             // 提供open()函数
#include <unistd.h>            // 提供close()函数
#include <errno.h>             // 提供strerror()函数和errno
#include <stdio.h>             // 提供输出函数
#include <string.h>            // 提供strerror函数

2、函数原型

int open(const char *pathname, int flags);
int open(const char *pathname, int flags, mode_t mode);

返回: 若成功为文件描述符,若出错为-1
功能: 打开或创建一个文件
参数
pathname:要打开或者创建的文件路径
flags:用来说明此函数的多个选择项
用下列一个或者多个常数进行按位或运算构成flags参数,这些常数定义在/usr/include/bits/fcntl.h中,在include fcntl.h时,会包含这个文件

常量名解释
O_RDONLY只读
O_WRONLY只写
O_RDWR读写
O_CREAT如果指定的文件不存在,则按照mode参数指定的文件权限来创建文件
O_EXCL如果同时指定了O_CREAT,而文件已经存在,则出错。可测试一个文件是否存在。但在网络文件系统进行操作时却没有保证
O_DIRECTORY如果参数pathname不是一个目录,则open出错
O_TRUNC如果文件存在,而且为只读或只写成功打开,则将其长度截短为0
O_APPEND以追加模式打开文件,每次写时加到文件尾端,但在网络文件系统进行操作时没有保证
O_NONBLOCK如果pathname指定的是是一个FIFO,一个块特殊文件或者一个字符特殊文件,则此选择项为此文件的本次打开操作和后续I/O操作设置非阻塞方式

mode:新建文件的访问权限,对于open函数而言,仅当创建新文件时才使用第三个参数。

二、creat函数

int creat(const char *pathname, mode_t mode);
返回: 若成功为只写打开的文件描述符,若出错为-1
功能: 创建一个新文件
等同于open (pathname, O_WRONLY | O_CREAT | O_TRUNC, mode) ;
以只写方式打开所创建的文件。

三、close函数

int close(int fd);

返回: 若成功为0,若出错为-1
功能: 关闭一个打开的文件
参数
fd:已打开文件的文件描述符
当一个进程终止时,他所有打开的文件都由内核自动关闭

四、read函数

ssize_t read(int fd, void *buf, size_t count);
返回: 读到的字节数,若已到文件尾为0,若出错为-1
功能: 从打开文件中读数据
参数:
fd:读取文件的文件描述符
buf:存放读取数据的缓存
count:要求读取一次数据的字节数

有多种情况可使实际读到的字节小于要求读取的字节数

  • 读普通文件时,在读到要求字节数之前已经到达文件尾端
  • 当从终端设备读取时,通常一次只能读取一行
  • 当从网络读时,网络中的缓冲机构可能造成返回值小于要求要读的字节数
  • 某些面向记录的设备,如磁带,一次最多返回一个记录
  • 进程由于信号造成中断

读操作从当前位移量处开始,在成功返回之前,该位移量增加实际读到的字节数==

五、write函数

ssize_t write(int fd, const void *buf, size_t count);
返回: 若成功为已写的字节数,若出错为-1
功能: 向打开的文件中写数据
参数:
fd:写入文件的文件描述符
buf:存放待写数据的缓存
count:要求写入一次数据的字节数

其返回值通常与参数count的值相同,否则表示出错
write出错的原因:磁盘已满,或者超过了对一个给定进程的文件见长度限制
对于普通文件,写操作从文件当前位移量处开始。如果在打开该文件时,指定了O_APPEND选择项,则在每次写操作前,将文件位移量设置在文件的当前结尾处。在一次写成功之后,该文件位移量增加实际写的字节数

示例

int cp(char* source,char* destination)
{
        int s = open(source,O_RDONLY);
        int d = open(destination,O_CREAT | O_WRONLY | O_TRUNC,0777);
        if(s == -1 || d == -1)
        {
                fprintf(stderr,"open file error %s \n",strerror(errno));
                return 0;
        }
        // 每次读取的大小可以根据设备的block_size来决定,可以通过 tune2fs -l /dev/sda1 查看
        int buffer_length = 888,read_flag = 0;
        char buffer[buffer_length];
        while((read_flag = read(s,buffer,buffer_length)) != 0)
        {
                // 只写入读取到的数据
                if(read_flag > write(d,buffer,read_flag))
                {       
                        fprintf(stderr,"write file error %s \n",strerror(errno));
                        return 0;
                }
                memset(buffer,'\0',buffer_length);
        }
        close(s);
        close(d);
        return 1;
}

lseek函数

off_t lseek(int fd,off_t offset, int whence);

  • 头文件:
#include <sys/types.h>
#include <unistd.h>
  • 返回:若成功则返回新的文件位移量(绝对偏移量);
  • 功能:定位一个以打开的文件
  • 参数

    • fd:已打开文件的文件描述符
    • offset:位移量
    • whence:定位的位置

      • SEEK_SET:将该文件的位移量设置为距文件开始处offset个字节
      • SEEK_CUR:将该文件的位移量设置为其当前值加offset,offset可为正或负
      • SEEK_END: offset,offset可为正或负
  • lseek也可用来确定所涉及的文件是否可以设置位移量。如果文件描述符引用的是一个管道或FIFO,则lseek返回-1,并将errno设置为EPIPE。
  • 每个打开文件都有一个与其相关联的"当前文件偏移量"。它是一个非负整数,用以度量从文件开始处计算的字节数。通常,读,写操作都从当前文件偏移量处开始,并将偏移量增加所读或写的字节数。按系统默认,当打开一个文件时,除非指定O_APPEND选择项,否则该位移量被设置为0.
  • 示例
// 创建黑洞文件
int file_hole(char* file_path)
{       
        int f = open(file_path,O_CREAT | O_WRONLY | O_TRUNC,0777);
        if(f == -1)
        {       
                perror("open or create file:");
                return 0;
        }
        char buffer[] = "abcdef";
        if(sizeof(buffer) != write(f,buffer,sizeof(buffer)))
        {       
                perror("write file:");
                return 0;
        }
        // 移出文件末尾,再进行写入
        lseek(f,8,SEEK_END); 
        if(sizeof(buffer) != write(f,buffer,sizeof(buffer)))
        {       
                perror("write file:");
                return 0;
        }
        close(f);
        return 1;
}
// cat函数
void cat(int argc,char* argv[])
{
        int in = STDIN_FILENO;
        int out = STDOUT_FILENO;
        if(argc == 1)
        {   
                cp_by_file_no(in,out);
        }   
        else
        {   
                for(int i = 1;i < argc;i++)
                {   
                        in = open(argv[i],O_RDONLY);
                        if(in == -1) 
                        {   
                                perror("open file error:");
                        }   
                        cp_by_file_no(in,out);
                }   
        }   
}

文件I/O的内核数据结构

  • 一个打开的文件在内核中使用三种数据结构(结构体)表示

    • 文件描述符表(使用open等函数返回的文件描述符其实就是文件描述表(结构体数组)的下表)

      • 文件描述符标志
      • 文件表项指针
    • 文件表项

      • 文件状态标志

        • 读,写,追加,同步和非阻塞等状态标志
      • 当前文件偏移量
      • i节点表项指针
      • 饮用计数器
    • i节点

      • 文件类型和对该文件的操作函数指针
      • 当前文件长度
      • 文件所有者
      • 文件所在的设备,文件访问权限
      • 指向文件数据在磁盘块上所在位置的指针等

dup与dup2函数

int dup(int oldfd);
int dup2(int oldfd,int newfd);

  • 头文件:
    #include <unistd.h>
  • 返回:成功返回新文件描述符,出错返回-1
  • 功能:文件描述符的复制
  • 参数

    • oldfd:原先的文件描述符
    • newer:新的文件描述符
  • 由dup返回的新文件描述符一定时当前可用文件描述符中的最小数值
  • 用dup2则可以用newfd参数指定新描述符的数值。如newfd已经打开,则先将其关闭。如若oldfd等于newfd,则dup2返回newfd,而不关闭它(就是把文件描述符表中下标为newfd的结构体中文件表项指针存放的地址切换成文件描述符表中下标为oldfd的结构体中文件表项指针存放的地址,就是指针间的赋值)
  • 在进程间通信时可用来改变进程的标准输入和标准输出设备
  • 示例
void cat(int argc,char* argv[])
{
        int flag_arr[4] = {-1,-1,-1,-1},i = 1,stdin_temp = -1,stdout_temp = -1,file_temp = -1,argc_temp = argc;
        if(argc > 2)
        {
                for(;i < (argc_temp - 1);i++)
                {
                        // 修改输入重定向
                        if(strcmp("+",argv[i]) == 0)
                        {
                                flag_arr[0] = i++;
                                flag_arr[1] = i;
                                // 备份下标准输入,函数执行完毕后恢复
                                stdin_temp = dup(STDIN_FILENO);
                                file_temp = open(argv[i],O_RDONLY);
                                if(file_temp == -1)
                                {
                                        perror("open input file error");
                                }
                                dup2(file_temp,STDIN_FILENO);
                                argc -= 2;
                        }
                        // 修改输出重定向
                        if(strcmp("-",argv[i]) == 0)
                        {
                                flag_arr[2] = i++;
                                flag_arr[3] = i;
                                // 备份下标准输入,函数执行完毕后恢复
                                stdout_temp = dup(STDOUT_FILENO);
                                file_temp = open(argv[i],O_CREAT | O_WRONLY | O_TRUNC,0777);
                                if(file_temp == -1)
                                {
                                        perror("create or open output file error");
                                }
                                dup2(file_temp,STDOUT_FILENO);
                                argc -= 2;
                        }
                }
        }
        // 同时输入了输入和输出
        if(flag_arr[0] != -1 && flag_arr[2] != -1)
        {
                argc = flag_arr[1] + 1;
                flag_arr[1] = -1;
        }
        int in = STDIN_FILENO;
        int out = STDOUT_FILENO;
        if(argc == 1)
        {
                cp_by_file_no(in,out);
        }
        else
        {
                for(i = 1;i < argc;i++)
                {
                        if(in_array(i,flag_arr,4) == 1)
                        {
                                continue;
                        }
                        in = open(argv[i],O_RDONLY);
                        if(in == -1)
                        {
                                perror("open file error:");
                        }
                        cp_by_file_no(in,out);
                }
        }
        // 恢复标准输入输出
        if(flag_arr[0] != -1)
        {
                dup2(stdin_temp,STDIN_FILENO);
        }
        if(flag_arr[2] != -1)
        {
                dup2(stdout_temp,STDOUT_FILENO);
        }
}

fcntl函数

int fcntl(int fd,int cmd);
int fcntl(int fd,int cmd,long arg);
int fcntl(int fd,int cmd,struct flock *lock);

  • 头文件:
#include <unistd.h>
#include <fcntl.h>
  • 返回:若成功则依赖于cmd,若出错为-1
  • 功能:可以改变已经打开文件的性质
  • cmd的常见取值

    • F_DUPFD

      • 复制文件描述符,新的文件描述符作为函数值返回
    • F_GETFD/F_SETFD

      • 获取/设置文件描述符,通过第三个参数设置
    • F_GETFL/F_SETFL

      • 获取/设置文件描述符标志,通过第三个参数设置
      • 可以更改的几个标志是:O_APPEND,O_NONBLOCK,SYNC,O_ASYNC(O_RDONLY,O_WRONLY,O_RDWR不适用)
  • 常见使用

    • 复制一个现存的描述符,新文件描述符作为函数值返回(cmd=F_DUPFD)
    • 获得/设置文件描述符标志(cmd=F_GETFD或F_SETFD)
    • 获得/设置文件状态标志(cmd=F_GETFL或F_SETFL)
    • 获得/设置文件锁(cmd=F_SETLK,cmd=F_GETLK、F_SETLKW)

      • 文件锁必须用到第三个参数,第三个参数为struck flock结构体指针
  • 示例
int set_fl(int fd,int flag)
{
        flag |= fcntl(fd,F_GETFL);
        if(fcntl(fd,F_SETFL,flag) < 0)
        {
                return 0;
        }
        return 1;
}
int clear_fl(int fd)
{
        int flag = fcntl(fd,F_GETFL);
        flag &= ~flag;
        if(fcntl(fd,F_SETFL,flag) < 0)
        {
                return 0;
        }
        return 1;
}

I/O处理方式

  • I/O阻塞模型

    • 若所调用的I/O函数没有完成相关功能就会使进程挂起,直到相关数据到达才会返回。如:终端,网络设备的访问
  • 非阻塞模型

    • 当请求的I/O操作不能完成时,则不让进程休眠,而且返回一个错误。如open,read,write访问
  • I/O多路转接模型

    • 如果请求的I/O操作阻塞,且她不是真正阻塞I/O,而且让其中的一个函数等待,在这期间,I/O还能进行其他操作。如:select函数。
  • 信号驱动I/O模型

    • 在这种模型下,通过安装一个信号处理程序,系统可以自动捕获特定信号的到来,从而启动I/O。
  • 异步I/O模型

    • 在这种模型下,当一个描述符已准备好,可以启动I/O时,进程会通知内核。有内核进行后续处理,这种用法现在较少。
        char str[888] = {'\0'};
        // 设置非阻塞
        set_fl(STDIN_FILENO,O_NONBLOCK);
        // 下面的代码不会等待
        read(STDIN_FILENO,str,888);
        printf("%s\n",str);

文件和目录

struct stat结构体

struct stat{
    mode_t    st_mode;    /* file type & permission */
    ino_t     st_ino;     /* i-node number */
    dev_t     st_dev;     /* device number(file system) */
    dev_t     st_rdev;    /* device number for special files */
    nlink_t   st_nlink;   /* number of links */
    uid_t     st_uid;     /* user ID of owner */
    gid_t     st_gid;     /* group ID of owner */
    off_t     st_size;    /* size in byte */
    time_t    st_atime;   /* time of last access */
    time_t    st_mtime;   /* time of last modification */
    time_t    st_ctime;   /* time of last file status change */
    blksize_t st_blksize; /* best I/O block size */
    blkcnt_t  st_blocks;  /* number of disk blocks allocated */
};

文件属性操作函数

int stat(const char* pathname,struct stat* buf);
int fstat(int fd,struct stat* buf);
int lstat(const char* pathname,struct stat* buf);

  • 头文件:
#include <sys/types.h>
#include <sys/stat.h>
  • 返回:成功返回0,出错返回-1
  • 功能:返回一个pathname路径或fd指定的文件的属性信息,存储在结构体buf中
  • 参数

    • pathname:文件路径名字
    • buf:struct stat结构体指针
  • lstat类似于stat,但是当命名的文件是一个符号连接时,lstat返回该符号连接的有关信息,而不是由该符号连接引用的文件的信息

linux中七种文件类型和七种宏

文件类型
普通文件(regular file)S_ISREG()
目录文件(directory file)S_ISDIR()
块特殊文件(block special file)S_ISBLK()
字符特殊文件(character special file)S_ISCHR()
管道文件 FIFO(named pipe)S_ISFIFO()
套接字(socket)S_ISSOCK()
符号链接(symbolic link)S_ISLNK()
  • 示例
void file_type(char* path)
{
        struct stat s;
        if(lstat(path,&s) == -1)
        {       
                perror("incorrect file");
                return;
        }
        char* str = "unknow type";
        if(S_ISREG(s.st_mode))
        {       
                str = "regular file";
        }
        else if(S_ISDIR(s.st_mode))
        {       
                str = "directory";
        }
        else if(S_ISBLK(s.st_mode))
        {
                str = "block special file";
        }
        else if(S_ISCHR(s.st_mode))
        {
                str = "character special file";
        }
        else if(S_ISFIFO(s.st_mode))
        {
                str = "FIFO";
        }
        else if(S_ISSOCK(s.st_mode))
        {
                str = "socket file";
        }
        else if(S_ISLNK(s.st_mode))
        {
                str = "symbolic link";
        }
        printf("%s : %s\n",path,str);
}
void print_file_stat(char* path)
{
        struct stat* s = malloc(sizeof(struct stat));
        if(stat(path,s) == -1)
        {
                perror("incorrect file : ");
        }
        printf("mode \t %d\nino \t %d\ndev \t %d\nrdev \t %d\nnlink \t %d\nuid \t %d\ngid \t %d\nsize \t %d\natime \t %d\nmtime \t %d\nctime \t %d\nblksize \t %d\nblocks \t %d\n",
                (int)s->st_mode,(int)s->st_ino,(int)s->st_dev,(int)s->st_rdev,(int)s->st_nlink,(int)s->st_uid,(int)s->st_gid,(int)s->st_size,(int)s->st_atime,(int)s->st_mtime,(int)s->st_ctime,(int)s->st_blksize,(int)s->st_blocks);
        free(s);
}

文件权限

  • 9种文件访问权限位

    • 用户权限

      • S_IRUSR,S_IWUSR,S_IXUSR
    • 组权限

      • S_IRGRP,S_IWGRP,S_IXGRP
    • 其他权限

      • S_IROTH,S_IWOTH,S_IXOTH
  • 文件权限通过按位或方式构造
  • 示例:
// 创建文件是给权限
int f1 = open("test.txt",O_CREAT | O_RDONLY,S_IWUSR | S_IRUSR | S_IWGRP);
int f2 = open("test.txt",O_CREAT | O_RDONLY,0620); // 与上面效果一致
// 输出文件权限
void file_permission(char* path)
{
        struct stat s;
        if(lstat(path,&s) == -1)
        {
                perror("incorret file");
                return;
        }
        printf("%c%c%c%c%c%c%c%c%c\n"
                ,(S_IRUSR & s.st_mode) ? 'r' : '-'
                ,(S_IWUSR & s.st_mode) ? 'w' : '-'
                ,(S_IXUSR & s.st_mode) ? 'x' : '-'
                ,(S_IRGRP & s.st_mode) ? 'r' : '-'
                ,(S_IWGRP & s.st_mode) ? 'w' : '-'
                ,(S_IXGRP & s.st_mode) ? 'x' : '-'
                ,(S_IROTH & s.st_mode) ? 'r' : '-'
                ,(S_IWOTH & s.st_mode) ? 'w' : '-'
                ,(S_IXOTH & s.st_mode) ? 'x' : '-'
        );
}

access函数

int access(const char* pathname, int mode);

  • 返回:成功执行时返回0,若出错为-1
  • 功能:检查是否可以对指定文件进行某种操作
  • 头文件
    #include <unistd.h>
  • 参数

    • pathname:文件路径
    • mode:文件访问权限

      • R_OK:判断文件是否有读权限
      • W_OK:判断文件是否有写权限
      • X_OK:判断文件是否有可执行权限
      • F_OK:判断文件是否存在
  • 示例
void file_access(char* path)
{
        if(access(path,F_OK) == -1)
        {
                printf("%s does not exist\n",path);
                return;
        }
        if(access(path,R_OK) == -1)
        {
                printf("%d cannot read file:%s\n",getpid(),path);
        }       
        if(access(path,W_OK) == -1)
        {
                printf("%d cannot write file:%s\n",getpid(),path);
        }
        if(access(path,X_OK) == -1)
        {
                printf("%d cannot excute file:%s\n",getpid(),path);
        }
}

linux文件系统的结构

  • 文件操作相关的基本元素是:目录结构,索引节点和文件的数据本身

    • 目录结构(目录项)
    • 索引节点(i节点)
    • 文件的数据
  • 文件系统(硬盘)的三个区域

    • 超级块:存放文件系统本身的结构信息
    • i-节点表:存放i节点信息列表
    • 数据区:存放文件内容

软链接与硬链接的区别

硬链接:会创建新目录项并指向原文件的i节点,并且文件的链接数会加1
软链接:会创建新目录项,新i节点,新数据块,新数据块存放的是原文件的路径

link函数

int link(const char* existing path,const char* newpath);

  • 返回:成功返回0,出错返回-1
  • 功能:创建一个指向现存文件链接(硬链接)
  • 创建条件

    • 针对文件创建链接
    • 必须是同一分区
    • 只有超级用户才能对目录建立链接
  • 示例
if(-1 == link(argv[1],argv[2]))
{
        printf("fail to create %s\n",argv[2]);
        return 1;
}

unlink函数

int link(const char* existing path,const char* newpath);

  • 返回:成功返回0,出错返回-1
  • 功能:删除pathname指定的硬链接,并将由pathname所引用的文件链接计数减1
  • 文件删除条件

    • 链接计数为0
    • 无其他进程打开该文件
  • 示例
if(argc < 2)
{
        printf("incorrect parameter\n");
        return 1;
}
if(access(argv[1],F_OK) == -1)
{
        printf("%s does not exist\n",argv[1]);
        return 1;
}
if(-1 == unlink(argv[1]))
{
        printf("fail to delete %s\n",argv[1]);
        return 1;
}

remove函数

int remove(const char* pathname);

  • 返回:成功返回0,出错返回-1
  • 功能:解除对一个文件或目录的链接
  • 头文件
#include <unistd.h>
  • 对于文件,remove的功能与unlink相同
  • 对于目录,remove的功能与rmdir相同

rename函数

int rename(const char* oldname,const char* newname);

  • 返回:成功返回0,出错返回-1
  • 功能:解除对一个文件或目录的链接
  • 头文件
#include <unistd.h>

symlink函数

int symlink(const char* actualpath,const char* sympath);

  • 返回:成功返回0,出错返回-1
  • 功能:创建一个符号链接(软链接)
  • 头文件
#include <unistd.h>
  • 创建符号链接并不要求actualpath存在
  • 可以跨文件系统建立符号链接
  • 示例
if(argc < 3)
{
        printf("incorrect parameter\n");
        return 1;
}
if(access(argv[1],F_OK) == -1)
{
        printf("%s does not exist\n",argv[1]);
        return 1;
}
if(access(argv[2],F_OK) == 0)
{
        printf("%s has alreay existed\n",argv[2]);
        return 1;
}
if(-1 == symlink(argv[1],argv[2]))
{
        printf("fail to create %s\n",argv[2]);
        return 1;
}

readlink函数

int readlink(const char * path ,char * buf,size_t bufsiz);

  • 返回:成功返回0,出错返回-1
  • 功能:打开该链接本身,并读该链接中的名字
  • 头文件
#include <unistd.h>
  • 示例
if(argc < 2)
{
        printf("incorrect parameter\n");
        return 1;
}
if(access(argv[1],F_OK) == -1)
{
        printf("%s does not exist\n",argv[1]);
        return 1;
}
const int buffer_size = 1024;
char buffer[1024] = {'\0'};
if(-1 == readlink(argv[1],buffer,buffer_size))
{
        printf("fail to delete %s\n",argv[1]);
        return 1;
}
write(STDOUT_FILENO,buffer,buffer_size);
write(STDOUT_FILENO,"\n",1);

Wireshark图解教程(简介、抓包、过滤器)

开发app需要抓手机的包,ios下面使用了这款软件,感觉还不错,看到这篇文章,记录的很详细,记录下
转载网址:http://blog.sina.com.cn/s/blog_5d527ff00100dwph.html

1.捕捉过滤器

捕捉过滤器的语法与其它使用Lipcap(Linux)或者Winpcap(Windows)库开发的软件一样,比如著名的TCPdump。捕捉过滤器必须在开始捕捉前设置完毕,这一点跟显示过滤器是不同的。

设置捕捉过滤器的步骤是:
- 选择 capture -> options。
- 填写"capture filter"栏或者点击"capture filter"按钮为您的过滤器起一个名字并保存,以便在今后的捕捉中继续使用这个过滤器。
- 点击开始(Start)进行捕捉。

语法: Protocol Direction Host(s) Value Logical Operations Other expression
例子: tcp dst 10.1.1.1 80 and tcp dst 10.2.2.2 3128

Wireshark图解教程(简介、抓包、过滤器) Protocol(协议):
可能的值: ether, fddi, ip, arp, rarp, decnet, lat, sca, moprc, mopdl, tcp and udp.
如果没有特别指明是什么协议,则默认使用所有支持的协议。

Wireshark图解教程(简介、抓包、过滤器) Direction(方向):
可能的值: src, dst, src and dst, src or dst
如果没有特别指明来源或目的地,则默认使用 "src or dst" 作为关键字。
例如,"host 10.2.2.2"与"src or dst host 10.2.2.2"是一样的。
Wireshark图解教程(简介、抓包、过滤器) Host(s):
可能的值: net, port, host, portrange.
如果没有指定此值,则默认使用"host"关键字。
例如,"src 10.1.1.1"与"src host 10.1.1.1"相同。

Wireshark图解教程(简介、抓包、过滤器) Logical Operations(逻辑运算):
可能的值:not, and, or.
否("not")具有最高的优先级。或("or")和与("and")具有相同的优先级,运算时从左至右进行。
例如,
"not tcp port 3128 and tcp port 23"与"(not tcp port 3128) and tcp port 23"相同。
"not tcp port 3128 and tcp port 23"与"not (tcp port 3128 and tcp port 23)"不同。


例子:

tcp dst port 3128 显示目的TCP端口为3128的封包。

ip src host 10.1.1.1 显示来源IP地址为10.1.1.1的封包。

host 10.1.2.3 显示目的或来源IP地址为10.1.2.3的封包。

src portrange 2000-2500 显示来源为UDP或TCP,并且端口号在2000至2500范围内的封包。

not imcp 显示除了icmp以外的所有封包。(icmp通常被ping工具使用)

src host 10.7.2.12 and not dst net 10.200.0.0/16 显示来源IP地址为10.7.2.12,但目的地不是10.200.0.0/16的封包。

(src host 10.4.1.12 or src net 10.6.0.0/16) and tcp dst portrange 200-10000 and dst net 10.0.0.0/8 显示来源IP为10.4.1.12或者来源网络为10.6.0.0/16,目的地TCP端口号在200至10000之间,并且目的位于网络10.0.0.0/8内的所有封包。


注意事项:

当使用关键字作为值时,需使用反斜杠“\”。
"ether proto \ip" (与关键字"ip"相同).
这样写将会以IP协议作为目标。

"ip proto \icmp" (与关键字"icmp"相同).
这样写将会以ping工具常用的icmp作为目标。

可以在"ip"或"ether"后面使用"multicast"及"broadcast"关键字。
当您想排除广播请求时,"no broadcast"就会非常有用。


查看 TCPdump的主页以获得更详细的捕捉过滤器语法说明。
在Wiki Wireshark website上可以找到更多捕捉过滤器的例子。

2.显示过滤器

通常经过捕捉过滤器过滤后的数据还是很复杂。此时您可以使用显示过滤器进行更加细致的查找。
它的功能比捕捉过滤器更为强大,而且在您想修改过滤器条件时,并不需要重新捕捉一次。
|语法:| Protocol | String 1 | String 2 | Comparison operator | Value | Logical expression | Other expression |
| ----- |:-------------:|:-------------:|:-------------:|:-------------:|:-------------:|:-------------:| -----:|
|例子:| ftp | passive | ip | == | 10.2.3.4 | xor | icmp.type |
Protocol(协议):

您可以使用大量位于OSI模型第2至7层的协议。点击"Expression..."按钮后,您可以看到它们。
比如:IP,TCP,DNS,SSH
Wireshark的网站提供了对各种 协议以及它们子类的说明。

Wireshark图解教程(简介、抓包、过滤器) String1, String2 (可选项):

协议的子类。
点击相关父类旁的"+"号,然后选择其子类。
Comparison operators (比较运算符):
可以使用6种比较运算符:

英文语法: c语言语法 含义
eq == 等于
ne != 不等于
gt > 大于
lt < 小于
ge >= 大于等于
le <= 小于等于

gcc以及gdb的基本使用

gcc语法:gcc [options] [filenames]
1、基本选项
1)-c:只是编译不链接,生成目标文件”.o”
2)-S:只是编译不汇编,生成汇编代码
3)-E:只进行预编译,不做其它处理
4)-g:在可执行程序中包含标准调试信息
5)-o file:指定输出文件
6)-v :打印出编译器内部编译各过程的命令行信息和编译器的版本
7)-std=name:指定C语言的标准(如:c99等)
8)-I dir :在头文件的搜索路径列表中添加dir目录
2、警告和出错选项
1)-ansi:支持符合ANSI标准的C程序
2)-pedantic:允许发出ANSI C标准所列的全部警告信息
3)-pedantic-error:允许发出ANSI C标准所列的全部错误信息
4)-w:关闭所有警告
5)-Wall:允许发出gcc所提供的所有有用的报警信息
3、优化
-O:减小代码的长度和执行时间,效果等价于O1,其中包括线程跳转和延迟退栈
-O2:除完成所有O1级别的优化之外,同时进行一些额外的调整工作,如处理器指令调度
-O3:除完成所有O2级别优化之外,还包括循环展开和其他一些与处理器特性相关的优化工作
数字越大优化的等级越高,也就意味着程序的运行越快,一般采用O2选项,他在优化长度,编译时间和代码大小之间取得了一个比较理想的平衡点
4、制作库文件
-L dir 在库文件搜索列表中添加dir目录
-static 链接静态库
-lname 链接名为name的库文件
-shared 表明是用共享库

一、gdb简介
1、GDB是GNU开源组织发布的一个强大的Unix/Linux下的程序调试工具
二、gdb作用
1、启动用户程序后,可以按照用户的要求随意运行程序。
2、可让被调试的程序在用户所设定的断点处停住
3、当程序被停住时,可以检查此时用户程序中所发生的事。
4、可动态改变用户程序的执行环境
三、gdb语法
1、gcc -g [其它选项] [文件名]
2、gdb 可执行文件‘
3、gdb进行调试的是可执行文件而不是源代码
4、对.c源文件进行编译一定要加上选项”-g”,这样编译出的可执行文件才包含调试信息。
四、gdb调试命令
1、l(list):查看所载入的文件
2、b(break):设置断点,程序运行到断点即可停止。
3、nfo b:查看设置的断点情况
4、r(run):从第一行开始运行代码,或者指定行开始,可在r后面加上行号。
5、p n:查看变量n的值
6、n(next):单步运行下一行代码(遇到函数不会进入函数)
7、s(step):单步运行下一行代码(遇到函数会进入函数)
8、c(continue):恢复程序的运行,执行剩余的程序。

使用git Rebase让历史变得清晰,合并git历史

当多人协作开发一个分支时,历史记录通常如下方左图所示,比较凌乱。如果希望能像右图那样呈线性提交,就需要学习git rebase的用法。

“Merge branch”提交的产生

我们的工作流程是:修改代码→提交到本地仓库→拉取远程改动→推送。正是在git pull这一步产生的Merge branch提交。事实上,git pull等效于get fetch origin和get merge origin/master这两条命令,前者是拉取远程仓库到本地临时库,后者是将临时库中的改动合并到本地分支中。

要避免Merge branch提交也有一个“土法”:先pull、再commit、最后push。不过万一commit和push之间远程又发生了改动,还需要再pull一次,就又会产生Merge branch提交。

使用git pull –r
修改代码→commit→git pull –rebase→git push 也就是将git merge origin/master替换成了git rebase origin/master,它的过程是先将HEAD指向origin/master,然后逐一应用本地的修改,这样就不会产生Merge branch提交了。具体过程见下文扩展阅读。

使用git rebase是有条件的,你的本地仓库要“足够干净”。可以用git status命令查看当前改动::

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean

本地没有任何未提交的改动,这是最“干净”的。稍差一些的是这样:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Untracked files:
  (use "git add <file>..." to include in what will be committed)
    test.txt
nothing added to commit but untracked files present (use "git add" to track)

即本地只有新增文件未提交,没有改动文件。我们应该尽量保持本地仓库的“整洁”,这样才能顺利使用git rebase。特殊情况下也可以用git stash来解决问题,有兴趣的可自行搜索。

修改git pull的默认行为

每次都加–-rebase似乎有些麻烦,我们可以指定某个分支在执行git pull时默认采用rebase方式:

$ git config branch.master.rebase true

如果你觉得所有的分支都应该用rebase,那就设置:

$ git config --global branch.autosetuprebase always

这样对于新建的分支都会设定上面的rebase=true了。已经创建好的分支还是需要手动配置的。

扩展阅读[1]:git rebase工作原理

在做项目开发时会用到分支,合并时采用以下步骤:

$ git checkout feature-branch
$ git rebase master
$ git checkout master
$ git merge --no-ff feature-branch
$ git push origin master

历史就成了这样:
转载自 http://www.cnblogs.com/UnGeek/p/5737653.html