本文主要是介绍Mjpeg-streamer源码学习笔记-Main-get_long_only(一),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目标文件:mjpg-stream/mjpg-stream.c
这一篇的主要难点是get_long(),get_long_only().
新手写,有不对的请大神指正,鼓励。
本人参考文章:
http://www.360doc.com/content/13/0913/13/13876325_314174121.shtml
http://blog.sina.com.cn/s/blog_a31ff26901013l22.html
---------------------------------------------------------------------------------------------------------------------------
一:直接对主函数main分析。遇到具体情况,具体往下延伸。
//char *input = "input_uvc.so --resolution 640x480 --fps 5 --device /dev/video0";
char *input[MAX_INPUT_PLUGINS];/* 这里MAX_INPUT_PLUGINS在.h文件中定为10 */
char *output[MAX_OUTPUT_PLUGINS]; /* 一个输入最大可以对应10个输出 */
int daemon = 0, i;/* 守护进程变量,守护进程作为重点,下一篇详述 */
size_t tmp = 0;
output[0] = "output_http.so --port 8080";/* 默认情况下将video0作为输入,http的8080端口作为输出 */
global.outcnt = 0;/* 代码中 参数行操作的计数 */
---------------------------------------------------------------------------------------------------------------------------
二:下面是一个while()循环,来解析main()函数后面所带的参数
/* parameter parsing */
while(1) {
int option_index = 0, c=0;
static struct option long_options[] = \ /* 长选项表,进行长选项的比对 */
{
{"h", no_argument, 0, 0}, /* 第一个参数为选项名,前面没有短横线。譬如"help"、"verbose"之类 */
{"help", no_argument, 0, 0}, /* 第二个参数描述了选项是否有选项参数 |no_argument 0 选项没有参数|required_argument 1 选项需要参数|optional_argument 2 选项参数可选|*/
{"i", required_argument, 0, 0}, /* 第三个参数指明长选项如何返回,如果flag为NULL,则getopt_long返回val。
{"input", required_argument, 0, 0}, * 否则返回0,flag指向一个值为val的变量。如果该长选项没有发现,flag保持不变.
{"o", required_argument, 0, 0}, */
{"output", required_argument, 0, 0}, /* 第四个参数是发现了长选项时的返回值,或者flag不是NULL时载入*flag中的值 */
{"v", no_argument, 0, 0},
{"version", no_argument, 0, 0},
{"b", no_argument, 0, 0}, /* 每个长选项在长选项表中都有一个单独条目,该条目里需要填入正确的数值。数组中最后的元素的值应该全是0。
{"background", no_argument, 0, 0}, *数组不需要排序,getopt_long()会进行线性搜索。但是,根据长名字来排序会使程序员读起来更容易.
{0, 0, 0, 0} */
};
---------------------------------------------------------------------------------------------------------------------------
三:接下来是getopt_long_only函数,重点分析
---------------------------------------------------------------------------------------------------------------------------
c = getopt_long_only(argc, argv, "", long_options, &option_index);
由于和后面的代码有关,故一起分析。
---------------------------------------------------------------------------------------------------------------------------
/* no more options to parse */
if (c == -1) break;
/* unrecognized option */
if(c=='?'){ help(argv[0]); return 0; }
switch (option_index) {
/* h, help */
case 0:
case 1:
help(argv[0]);
return 0;
break;
/* i, input */
case 2:
case 3:
input = strdup(optarg);
break;
/* o, output */
case 4:
case 5:
output[global.outcnt++] = strdup(optarg);
break;
/* v, version */
case 6:
case 7:
printf("MJPG Streamer Version: %s\n" \
"Compilation Date.....: %s\n" \
"Compilation Time.....: %s\n", SOURCE_VERSION, __DATE__, __TIME__);
return 0;
break;
/* b, background */
case 8:
case 9:
daemon=1;
break;
default:
help(argv[0]);
return 0;
}
}
---------------------------------------------------------------------------------------------------------------------------
代码里出现了help自定义函数,一个switch选择结构,c为flag作为判断标准,同时c也是getopt_long_only的返回值。
strdup函数,变量optarg,变量daemon。
3.1 get_long_only函数:
#include <getopt.h>
int getopt_long_only(int argc, char * const argv[],
const char *optstring, const struct option *longopts, int *longindex);
说明:函数中的参数说明
~1+2 argc和argv通常直接从main()到两个参数传递而来
~3 optsting是选项参数组成的字符串,如果该字符串里任一字母后有冒号,那么这个选项就要求有参数
~4 下一个参数是指向数组的指针,这个数组是option结构数组,option结构称为长选项表,
其声明如下:
struct option
{
const char *name;
int has_arg;
int *flag;
int val;
};
_1 const char *name:选项名,前面没有短横线。譬如"help"、"verbose"之类。 _2 int has_arg:描述长选项是否有选项参数,如果有,是哪种类型的参数,其值见下表:
----------------------------------------------------
符号常量
no_argument
required_argument
optional_argument
----------------------------------------------------
_3 int *flag:
如果该指针为NULL,那么getopt_long返回val字段的值;
如果该指针不为NULL,那么会使得它所指向的结构填入val字段的值,同时getopt_long返回0
_4 int val:
如果flag是NULL,那么val通常是个字符常量,如果短选项和长选项一致,那么该字符就应该与optstring中出现的这个选项的参数相同;
对于options类型参数可以有两种方式:
1)短选项(short options):顾名思义,就是短小参数。它们通常包含一个连字号和一个字母(大写或小写字母)。例如:-s,-h等。
2)长选项(long options):长选项,包含了两个连字号和一些大小写字母组成的单词。例如,--size,--help等。
记住几种常见返回值:
(a)每次调用该函数,它都会分析一个选项,并且返回它的短选项,如果分析完毕,即已经没有选项了,则会返回-1。
(b)如果getopt_long_only或者getopt_long在分析选项时,遇到一个没有定义过的选项,则返回值为‘?’,此时,程序员可以打印出所定义命令行的使用信息给用户。
(c)当处理一个带参数的选项时,全局变量optarg会指向它的参数
(d)当函数分析完所有参数时,全局变量optind(into argv)会指向第一个‘非选项’的位置
讲了这么多。还是抽象。上实例解析getopt:
(getopt_long和getopt_long_only类似,以getlong讲解,参数是一样的)
实例1:
#include <stdio.h>
#include <getopt.h>
char *l_opt_arg;
char* const short_options = "nbl:";
struct option long_options[] = {
{ "name",
{ "bf_name",
{ "love",
{
};
int main(int argc, char *argv[])
{
int c;
while((c = getopt_long (argc, argv, short_options, long_options, NULL)) != -1)
{
switch (c)
{
case 'n':
printf("My name is XL.\n");
break;
case 'b':
printf("His name is ST.\n");
break;
case 'l':
l_opt_arg = optarg;
printf("Our love is %s!\n", l_opt_arg);
break;
}
}
return 0;
}
编译并运行:
[root@localhost liuxltest]# gcc -o getopt getopt.c
[root@localhost liuxltest]# ./getopt -n -b -l forever
My name is XL.
His name is ST.
Our love is forever!
[root@localhost liuxltest]#
[root@localhost liuxltest]# ./getopt -nb -l forever
My name is XL.
His name is ST.
Our love is forever!
[root@localhost liuxltest]# ./getopt -nbl forever
My name is XL.
His name is ST.
Our love is forever!
编译结果分析:
char* const short_options = "nbl:";这一句,表示nb不需要参数,l需要参数
无冒号不要参数,一个冒号需要参数,两个冒号参数可选.
所以forever是-l命令的参数.故需要char *l_opt_arg;
如我有一个程序,有两个选项,-a, -b, 我输入的时候是
这就解释了-nbl的输入
现在对于处理命令行参数的操作是不是明朗一点了。
再看个例子
实例2:
#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
char *l_opt_arg;
const char* const short_options = "myl:";
struct option long_options[] = {
};
int main(int argc, char *argv[])
{