唠嗑
最近看了维神的《沙丘》,我觉得是真的好看,配乐精彩绝伦,构图美轮美奂,场景气势磅礴,但是不是适合所有人;在各种廉价爆米花电影充斥主流商业片的今天,还能看到这么一部如此古典叙事且代表着好莱坞最高制作水准的巨作,简直幸运!
##系列文章
高通msm-V4L2-Camera驱动浅析1-初识
高通msm-V4L2-Camera驱动浅析2-框架详解
高通msm-V4L2-Camera驱动浅析3-session
高通msm-V4L2-Camera驱动浅析4-stream
高通msm-V4L2-Camera驱动浅析5-buffer
一、session(会话)的设计思路
在微信聊天的时候,我们想要跟人沟通联系,就会创建一个session(会话),多个人单独聊天,就会有多个session;
每一个session负责管理所有的资源,比如表情包、图片、聊天记录等。
高通的思路也是如此:
- 将camera的所有功能划分为不同的模块,让模块自己来决定自己的事情(高内聚,低耦合),模块需要有统一的接口和格式。
- 模块中有端口,通过端口把模块连接起来,又把模块挂在总线上。
- 每一个端口的连接就是一个流,把这些流用pipeline来管理。
- 每次启动一个camera就创建一个会话,由这个会话来管理此camera的一切事物。
- 对于每一个会话,模块是共享的,它可以是camera的硬件资源也可以是其它资源(如一些软件算法等资源)。
二、一个session是如何创建的
2.1、session的数据结构
msm_session
struct msm_session {
struct list_head list;
/* session index */
unsigned int session_id;
/* event queue sent by imaging server */
struct msm_event event_q;
/* ACK by imaging server. Object type of
* struct msm_command_ack per open,
* assumption is application can send
* command on every opened video node
*/
struct msm_queue_head command_ack_q;
/* real streams(either data or metadate) owned by one
* session struct msm_stream
*/
struct msm_queue_head stream_q;
struct mutex lock;
struct mutex lock_q;
struct mutex close_lock;
rwlock_t stream_rwlock;
struct kgsl_pwr_limit *sysfs_pwr_limit;
}
msm_event
/** msm_event:
*
* event sent by imaging server
**/
struct msm_event {
struct video_device *vdev;
atomic_t on_heap;
};
- struct list_head list:链表,用来管理所有的会话
- unsigned int session_id:会话id
- msm_event event_q:video_device 实例
- struct msm_queue_head command_ack_q:cmd队列
- struct msm_queue_head stream_q:stream队列
这里最重要的就是msm_event event_q,本质上就是一个video_device 实例。
另外还有cmd队列和stream队列比较重要。
2.2 session和video_device的关系
png)
2.3 video_device、v4l2_device和v4l2_subdev的关系
2.4 session的创建
- 1.全局session队列的初始化
struct msm_queue_head {
struct list_head list;
spinlock_t lock;
int len;
int max;
};
static struct msm_queue_head *msm_session_q;
static int msm_probe(struct platform_device *pdev)
{
···
//申请内存
msm_session_q = kzalloc(sizeof(*msm_session_q), GFP_KERNEL);
//初始化
msm_init_queue(msm_session_q);
···
}
在msm_probe时,msm_session_q队列就会申请内存,然后初始化。
- 2.session的创建
int msm_create_session(unsigned int session_id, struct video_device *vdev)
{
struct msm_session *session = NULL;
//判断msm_session_q队列是否为空
if (!msm_session_q) {
pr_err("%s : session queue not available Line %d\n",
__func__, __LINE__);
return -ENODEV;
}
//根据session_id查找当前会话是否在全局session队列中
session = msm_queue_find(msm_session_q, struct msm_session,
list, __msm_queue_find_session, &session_id);
//如果会话已经存在,直接返回
if (session) {
pr_err("%s: Session exist session_id=%d\n",
__func__, session_id);
return -EINVAL;
}
//申请内存空间
session = kzalloc(sizeof(*session), GFP_KERNEL);
//赋值session_id
session->session_id = session_id;
//赋值video_device设备
session->event_q.vdev = vdev;
//初始化cmd队列
msm_init_queue(&session->command_ack_q);
//初始stream队列
msm_init_queue(&session->stream_q);
//入队:将新建的session加入全局队列msm_session_q
msm_enqueue(msm_session_q, &session->list);
mutex_init(&session->lock);
mutex_init(&session->lock_q);
mutex_init(&session->close_lock);
rwlock_init(&session->stream_rwlock);
return 0;
}
- 一个会话里面,维护了video_device,同时创建了cmd队列,和stream队列,最后把该session加入全局队列msm_session_q进行管理,如下图:
会话的创建流程,上一篇文章有讲到:
rc = msm_create_session(pvdev->vdev->num, pvdev->vdev);
这里第一个参数是session_id = pvdev->vdev->num;
也就是对应我们video1/video2里的1和2;
即session_id = 1或者2
Stay Hungry,Stay Foolish!