Webbench源码学习
源码解析
webbench.c
1.main
提供程序入口,解析参数进行网络请求相关变量设置。
* volatile
代码中使用了 volatile 关键字来修饰 int 变量 timerexpired 防止编译器对其进行优化。
嵌入式编程中经常用到 volatile这个关键字,用法可以归结为以下两点:
一:告诉compiler不能做任何优化
比如要往某一地址送两指令:
int *ip =...; //设备地址
*ip = 1; //第一个指令
*ip = 2; //第二个指令
以上程序compiler可能做优化而成:
int *ip = ...;
*ip = 2;
结果第一个指令丢失。如果用volatile, compiler就不允许做任何的优化,从而保证程序的原意。即使你要compiler做优化,它也不会把两次付值语句间化为一。它只能做其它的优化。这对device driver程序员很有用。
二:表示用volatile定义的变量会在程序外被改变,每次都必须从内存中读取,而不能把他放在cache或寄存器中重复使用。
volatile char a;
a=0;
while(!a)
{
//do some things;
}
doother();
如果没有 volatile doother()不会被执行
* 命令行获取参数 getopt
众所周知,C程序的主函数有两个参数,其中,第一个参数是整型,可以获得包括程序名字的参数个数,第二个参数是字符数组指针或字符指针的指针,可以按顺序获得命令行上各个字符串参数。
其原形是:
int main(int argc, char *argv[]);
或者
int main(int argc, char **argv);
在Unix/Linux的正式的项目上,程序员通常会使用getopt()或者getopt_long()来获得输入的参数。两者的一个区别在于getopt()只支持短格式参数,而getopt_long()既支持短格式参数,又支持长格式参数。
短格式:./destroy -f cdr -o cdr.txt -c cdr.desc -k 123456
长格式:./destroy –file cdr –output cdr.txt –config cdr.desc –keyword 123456
引入了getopt()和getopt_long()的项目,设计者可以按需要,方便地增加参数,或者随意地放置参数的先后次序,只需要在程序中判断,哪些参数是必须的就可以了。
#include <unistd.h>
extern char *optarg; //选项的参数指针
extern int optind, //下一次调用getopt的时,从optind存储的位置处重新开始检查选项。
extern int opterr, //当opterr=0时,getopt不向stderr输出错误信息。
extern int optopt; //当命令行选项字符不包括在optstring中或者选项缺少必要的参数时,该选项存储在optopt 中,getopt返回'?'
int getopt(int argc, char * const argv[], const char *optstring);
调用一次,返回一个选项。 在命令行选项参数再也检查不到optstring中包含的选项时,返回-1,同时optind储存第一个不包含选项的命令行参数。
首先说一下什么是选项,什么是参数。
1.单个字符,表示选项,
2.单个字符后接一个冒号:表示该选项后必须跟一个参数。参数紧跟在选项后或者以空格隔开。该参数的指针赋给optarg。
3 单个字符后跟两个冒号,表示该选项后必须跟一个参数。参数必须紧跟在选项后不能以空格隔开。该参数的指针赋给optarg。(这个特性是GNU的扩张)。
例如gcc -g -o test test.c ,其中g和o表示选项,test为选项o的参数。
扫描过程中,optind是下一个选项的索引, 非选项参数将跳过。扫描结束后,optind将指向第一个非选项的参数。
while((opt=getopt_long(argc,argv,"912Vfrt:p:c:?h",long_options,&options_index))!=EOF )
long_options指向的是一个由option结构体组成的数组,那个数组的每个元素,指明了一个“长参数”(即形如–name的参数)名称和性质:
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
name 是参数的名称
has_arg 指明是否带参数值,其数值可选:no_argument (即 0) 表明这个长参数不带参数(即不带数值,如:–name);required_argument (即 1) 表明这个长参数必须带参数(即必须带数值,如:–name Bob);optional_argument(即2)表明这个长参数后面带的参数是可选的,(即–name和–name Bob均可)
flag 当这个指针为空的时候,函数直接将val的数值从getopt_long的返回值返回出去,当它非空时,val的值会被赋到flag指向的整型数中,而函数返回值为0
val 用于指定函数找到该选项时的返回值,或者当flag非空时指定flag指向的数据的值。
static const struct option long_options[]=
{
{"force",no_argument,&force,1},
{"reload",no_argument,&force_reload,1},
{"time",required_argument,NULL,'t'},
{"help",no_argument,NULL,'?'},
{"http09",no_argument,NULL,'9'},
{"http10",no_argument,NULL,'1'},
{"http11",no_argument,NULL,'2'},
{"get",no_argument,&method,METHOD_GET},
{"head",no_argument,&method,METHOD_HEAD},
{"options",no_argument,&method,METHOD_OPTIONS},
{"trace",no_argument,&method,METHOD_TRACE},
{"version",no_argument,NULL,'V'},
{"proxy",required_argument,NULL,'p'},
{"clients",required_argument,NULL,'c'},
{NULL,0,NULL,0}
};
* Tips 多个case执行相同数据段
case ':':
case 'h':
case '?': usage();return 2;break;