RIL层源码分析w(8)

2019-09-01 20:03

do {

//以r结尾

written = write (s_fd, \

} while ((written < 0 && errno == EINTR) || (written == 0));

return 0; }

经过上面的操作,就将一条命令传输到了Modem侧。

上面说道,at_send_command_full_nolock函数的另一个作用是阻塞当前线程,等待Modem回应,那么,如何实现阻塞的过程?又需要在什么样的情况下解除阻塞状态?又是如何在解除阻塞时把Modem的数据读取出来呢?这一串的疑问我们在接下来的小节中讲解。

3.3、reference通过readerLoop得到Modem回应后把数据返回给Eventloop

我们在上面的at_send_command_full_nolock函数中,调用writeline将命令写入Modem后,还做了一个很重要的动作,就是阻塞当前线程,等待Modem回应。我们再次回到at_send_command_full_nolock: static int at_send_command_full_nolock (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) {

//给Modem发消息AT err = writeline (command);

//创建新的sp_response作为回应 sp_response = at_response_new();

//上面发送完消息后需要阻塞等待Modem回应

while (sp_response->finalResponse == NULL && s_readerClosed == 0) { if (timeoutMsec != 0) {

//线程进入阻塞状态,等待另一线程满足s_commandcond 后解除

err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); } }

if (pp_outResponse == NULL) { //释放sp_response

at_response_free(sp_response); } else {

reverseIntermediates(sp_response); //将回应发送给当初请求AT的线程 *pp_outResponse = sp_response; } return err; }

上面的sp_response是返回给RILC的数据。而while循环中就是在阻塞状态下等待Modem的回应。这里需要简要说明一下pthread_cond_timeout_np的作用,pthread_cond_timeout_np的第一个参数s_commandcond是一种条件变量,而条件变量是利用线程间共享的全局变量进行同步的一种机制,主要包括两个动作:一个线程等待\条件变量的条件成立\而挂起;另一个线程使\条件成立\(给出条件成立信号)。为了防止竞争,条件变量的使用总是和一个互斥锁结合在一起。

在这里,为了等待s_commandcond条件变量而自动阻塞了当前线程。那么,只有当另一个线程通过pthread_cond_signal接口是s_commandcond条件满足时,当前阻塞的线程才会被唤醒。 那么是在哪里去唤醒当前线程的呢?

我们分析一下,当我们发送数据或命令给Modem的时候,阻塞了当前的线程,阻塞的目的就是等待Modem的回应,而如果Modem有数据上来,那么肯定是先被reference的ReaderLoop检测到并处理,因此,也应该是在ReaderLoop的消息处理中去唤醒当前阻塞的线程,而且应该把Modem的反馈传输给阻塞线程。

我们直接来看ReaderLoop的处理函数,因为作为Modem的回应,当前消息一定不是URC消息,因此处理函数就是processLine: @atchannel.c

static void processLine(const char *line) {

if (sp_response == NULL) {

} else if (isFinalResponseSuccess(line)) { sp_response->success = 1; //发送回应消息给EventLoop handleFinalResponse(line); } else if (isFinalResponseError(line)) {

} else if (s_smsPDU != NULL && 0 == strcmp(line, \ } else switch (s_type) { case NO_RESULT: case NUMERIC: case SINGLELINE:

if (sp_response->p_intermediates == NULL && strStartsWith (line, s_responsePrefix) ) {

addIntermediate(line); } else {

/* we already have an intermediate response */ handleUnsolicited(line); } break; case MULTILINE: break; } }

上面在分析processLine时就说过,Modem给的数据可能有很多行,组后一行是OK的标志位,而之前的行都是有效数据。我们还知道,对于得到SIM卡状态这个请求,他的s_type是SINGLELINE(传递给reference时决定的)。

因此,我们接受的Modem数据应该先被switch中的SINGLELINE处理,而这一步的处理就是把Modem的有效数据放到sp_response->p_intermediates中: static void addIntermediate(const char *line) {

ATLine *p_new;

p_new = (ATLine *) malloc(sizeof(ATLine)); p_new->line = strdup(line);

p_new->p_next = sp_response->p_intermediates; sp_response->p_intermediates = p_new; }

等有效数据处理完后,再次进入processLine时,遇到了标志位行,因此isFinalResponseSuccess判断成立,去唤醒另一端阻塞的线程:

static void handleFinalResponse(const char *line) {

//把回应消息返回给RIL

sp_response->finalResponse = strdup(line);

//s_commandcond条件变量的条件得到满足,将会唤醒相应的阻塞线程 pthread_cond_signal(&s_commandcond); }

到这里,完全符合我们的预期,也就是在ReaderLoop的处理过程中,满足条件变量,从而使等待在pthread_cond_timeout_np的线程脱离阻塞状态,同时,把Modem的回应(line)传递给sp_response->p_intermediates。

此时,我们可以再次回到被阻塞的线程,看看接下来的数据传输过程: @atchannel.c

static int at_send_command_full_nolock (const char *command, ATCommandType type, const char *responsePrefix, const char *smspdu, long long timeoutMsec, ATResponse **pp_outResponse) {

//给Modem发消息AT err = writeline (command);

//创建新的sp_response作为回应 sp_response = at_response_new();

//上面发送完消息后需要阻塞等待Modem回应

while (sp_response->finalResponse == NULL && s_readerClosed == 0) { if (timeoutMsec != 0) {

//线程进入阻塞状态,等待另一线程满足s_commandcond后解除

err = pthread_cond_timeout_np(&s_commandcond, &s_commandmutex, timeoutMsec); } }

if (pp_outResponse == NULL) { //释放sp_response

at_response_free(sp_response); } else {

reverseIntermediates(sp_response); //将回应发送给当初请求AT的线程 *pp_outResponse = sp_response; } return err; }

当这个函数从pthread_cond_timeout_np中唤醒后,如果当前的命令确实要求Modem给出相应的回应,就会把回应的数据放到pp_outResponse中,返回给上层使用。我们知道,当前的sp_response->finalResponse就是Modem给出的回应。接着,at_send_command_full_nolock就返回了。 我们再次回顾一下当初调用到pthread_cond_timeout_np的路径:


RIL层源码分析w(8).doc 将本文的Word文档下载到电脑 下载失败或者文档不完整,请联系客服人员解决!

下一篇:2018年湖南省政府采购评审专家库培训测评-多选题部分答案

相关阅读
本类排行
× 注册会员免费下载(下载后可以自由复制和排版)

马上注册会员

注:下载文档有可能“只有目录或者内容不全”等情况,请下载之前注意辨别,如果您已付费且无法下载或内容有问题,请联系我们协助你处理。
微信: QQ: