本文主要是介绍Mjpeg-streamer源码学习笔记-Main-动态库插件(三),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
目标文件:mjpg-stream/mjpg-stream.c + mjpg-stream.h + input.h + output.h
这一篇的主要难点是main()中的结构体globals引出的动态链接库,插件,条件变量,互斥锁等问题。
新手写,有不对的请大神指正,鼓励。
本人参考文章:
http://www.360doc.com/content/13/0913/13/13876325_314174121.shtml
http://www.cnblogs.com/ardar/articles/357321.html
一:结构体介绍
globals
------------------------------------------------------------------------------
//
typedef struct _globals globals;
struct _globals {
};
------------------------------------------------------------------------------
input
------------------------------------------------------------------------------
//structure to store variables/functions for input plugin
typedef struct _input input;
struct _input {
};
------------------------------------------------------------------------------
output
------------------------------------------------------------------------------
//structure to store variables/functions for output plugin
typedef struct _output output;
struct _output {
};
------------------------------------------------------------------------------
input_parameter
------------------------------------------------------------------------------
//parameters for input plugin
typedef struct _input_parameter input_parameter;
struct _input_parameter {
};
------------------------------------------------------------------------------
output_parameter
------------------------------------------------------------------------------
//parameters for output plugin
typedef struct _output_parameter output_parameter;
struct _output_parameter {
};
------------------------------------------------------------------------------
input_format
------------------------------------------------------------------------------
typedef struct _input_format input_format;
struct _input_format {
};
------------------------------------------------------------------------------
input_resolution
------------------------------------------------------------------------------
typedef struct _input_resolution input_resolution;
struct _input_resolution {
};
------------------------------------------------------------------------------
control
------------------------------------------------------------------------------
typedef struct _control control;
struct _control {
};
------------------------------------------------------------------------------
二:源码分析
------------------------------------------------------------------------------
铺垫代码
------------------------------------------------------------------------------
这段代码确保了至少有一个输出插件选中
------------------------------------------------------------------------------
------------------------------------------------------------------------------
------------------------------------------------------------------------------
打开输出插件代码
------------------------------------------------------------------------------
------------------------------------------------------------------------------
运行插件代码直到Main()结束
------------------------------------------------------------------------------
//start to read the input, push pictures into global buffer
//开始读取输入,把照片放到全局缓冲区
------------------------------------------------------------------------------
至此,main函数的代码已经贴完。但具体还有很多细节没分析,下面逐个分析。
三:动态链接库
在上面加粗的很多函数中,见到了dlopen,dlerror等函数。下面就动态链接库内容分析
3.1 动态链接库的操作函数
~1 void *dlopen(const char *filename, int flag);
flag表示在什么时候解决未定义的符号(调用)。取值有两个:
1) RTLD_LAZY:表明在动态链接库的函数代码执行时解决。
2) RTLD_NOW : 表明在dlopen返回前就解决所有未定义的符号,一旦未解决,dlopen将返回错误。
dlopen调用失败时,将返回NULL值,否则返回的是操作句柄。
~2 const char *dlerror(void);
当动态链接库操作函数执行失败时,dlerror可以返回出错信息,返回值为NULL时表示操作函数执行成功。
~3 void *dlsym(void *handle, const char *symbol);
~4 int dlclose(void *handle);
dlclose用于关闭指定句柄的动态链接库,只有当此动态链接库的使用计数为0时,才会真正被系统卸载。
注意:Link with -ldl.
3.2 Linux动态链接库简介
大家都知道,在WINDOWS系统中有很多的动态链接库(以.DLL为后缀的文件,DLL即Dynamic Link Library)。这种动态链接库,和静态函数库不同,它里面的函数并不是执行程序本身的一部分,而是根据执行程序需要按需装入,同时其执行代码可在多个执行程序间共享,节省了空间,提高了效率,具备很高的灵活性,得到越来越多程序员和用户的青睐
在linux下动态链接库,在/lib目录下,就有许多以.so作后缀的文件,,这就是LINUX系统应用的动态链接库,只不过与WINDOWS叫法不同,它叫so,即Shared Object,共享对象。
在LINUX下,静态函数库是以.a作后缀的。
3.3动态链接库程序示例
#include"stdio.h"
#include"dlfcn.h"
#define SOFILE "./my.so"
#define SHARED
#include"datetime.h"
main()
{
DATETYPE d;
TIMETYPE t;
void *dp;
char *error;
puts("动态链接库应用示范");
dp=dlopen(SOFILE,RTLD_LAZY);
if (dp==NULL)
{
fputs(dlerror(),stderr);
exit(1);
}
getdate=dlsym(dp,"getdate");
error=dlerror();
if (error)
{
}
{
}
}
3.4 小结
LINUX创建与使用动态链接库并不是一件难事。
编译函数源程序时选用-shared选项即可创建动态链接库,注意应以.so后缀命名,最好放到公用库目录(如/lib,/usr/lib等)下面,并要写好用户接口文件,以便其它用户共享。
使用动态链接库,源程序中要包含dlfcn.h头文件,写程序时注意dlopen等函数的正确调用,编译时要采用-rdynamic选项与-ldl选项,以产生可调用动态链接库的执行代码。
四:字符串操作
在上面加粗的很多函数中,见到了strchr,strdup,strndup等函数。下面就字符串操作内容进行简单介绍
----------------------------------------------------------------------------------------------
#include<string.h>
char *strchr(const char *s, int c);
char *strrchr(const char *s, int c);
char *strdup(const char *s);
char *strndup(const char *s, size_t n);
char *strdupa(const char *s);
char *strndupa(const char *s, size_t n);
----------------------------------------------------------------------------------------------
五:条件变量和互斥锁
在上面加粗的很多函数中,见到了pthread_mutex_init,pthread_cond_init等函数。
这里涉及到很重要的线程问题。
将在下一篇(四)详细讲述线程和线程控制,并举出大量实例来分析。
所以这里一笔带过
六:源码中的两个函数
6.1 signal_handler
--------------------------------------------------------
void signal_handler(int sig)
{
}
--------------------------------------------------------
6.1.1 usleep函数
--------------------------------------------------------
usleep功能把进程挂起一段时间, 单位是微秒(千分之一毫秒);
头文件: <unistd.h>
语法: void usleep(int micro_seconds);
返回值: 无
内容说明:本函数可暂时使程序停止执行。参数 micro_seconds 为要暂停的微秒数(us)。
--------------------------------------------------------
6.1.2 线程函数pthread_cond_destroy,pthread_mutex_destroy
--------------------------------------------------------
和线程有关的,一笔带过,后面详细讲。
--------------------------------------------------------
6.1.3 函数功能总结
--------------------------------------------------------
我们来看看这个函数到底干了什么
最重要的几步:
~1 设置global.stop=1
~2 挂起进程 usleep
~3 逐个分别运行输入插件和输出插件的函数stop
~4 逐个分别销毁互斥锁和条件变量pthread_cond_destroy,pthread_mutex_destroy
~5 挂起进程 usleep
~6 逐个分别关闭输入插件和输出插件的动态链接库
~7 关闭系统日志 closelog
--------------------------------------------------------
6.2 split_parameters
代码中:
split_parameters(global.in[i].param.parameters, &global.in[i].param.argc, global.in[i].param.argv);
split_parameters(global.out[i].param.parameters, &global.out[i].param.argc, global.out[i].param.argv);
--------------------------------------------------------
int split_parameters(char *parameter_string, int *argc, char **argv)
{
}
--------------------------------------------------------
6.2.1 strtok函数
--------------------------------------------------------
char *strtok(char s[], const char *delim);
分解字符串为一组字符串。s为要分解的字符串,delim为分隔符字符串。
从s开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。
所有delim中包含的字符都会被滤掉,并将被滤掉的地方设为一处分割的节点。
strtok是一个线程不安全的函数,因为它使用了静态分配的空间来存储被分割的字符串位置
线程安全的函数叫strtok_r
例如:strtok("abc,def,ghi",","),最后可以分割成为abc def ghi.尤其在点分十进制的IP中提取应用较多。
--------------------------------------------------------
6.2.2 函数小结
名字就是分割参数,利用strtok函数做到这一点。
到最后,是通过while,把所有的传入参数:
1,先给parameter_string
2,通过strdup复制,传给arg
3,通过strtok分割,传给argv[x]数组
4,直到count到32,代表所有的输入输出插件的参数全部分割存储完毕。
6.3 pause函数
--------------------------------------------------------
功能:让进程暂停直到信号出现
相关函数:kill,signal,sleep
表头文件: #include<unistd.h>
定义函数: int pause(void);
函数说明: pause()会令目前的进程暂停(进入睡眠状态),直到被信号(signal)所中断。
返回值: 只返回-1。
--------------------------------------------------------
至此,mjpg-streamer.c + mjpg-streamer.h + input.h + output.h + utils.c + utils.h 全部内容已经分析完了。
下一篇,我们将会抛开源码,着重讲线程,线程控制,多线程编程的应用以解释源码中互斥锁和条件变量的运用。
转自:http://blog.csdn.net/s419101357/article/details/11827809
这篇关于Mjpeg-streamer源码学习笔记-Main-动态库插件(三)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!