IPC的使用
IPC,Inter-Processor Communication是SYS/BIOS处理核间通信的组件:
IPC的几种应用方式:
1.最小使用(Minimal use)
这种情况是通过核间的通知机制(notification)来实施的,而一个通知所携带的信息是非常小的(一般是32bits),所以称为最小使用。这种方式一般是用于处理核间的简单同步,却无法处理复杂的消息传递。
这种情况下,需要利用到Notify模块的APIs函数,比如通过Notify_sendEvent()函数给某个特定核传递一个事件,我们可以给特定事件动态注册反馈函数。由于一个通知(notification)所携带的信息是极少的,所以只能给处理器发送一个事件号,而这个事件号所代表的反馈函数决定之后的动作。另外一些数据以函数参数方式,也可以被送出。

2.增加数据通路(Add data passing)
这种情况是在前面的最小使用机制下,在核间增加了一个传递链表元素的数据通路,这个链表的实施一般是使用共享内容并通过门(gates)来管理同步。

3.增加动态分配(Add dynamic allocation)
这种情况下,增加了从堆中动态分配链表元素的功能。
这种情况在上种情况下,增加了一个Heap*MP模块,这个模块主要用于从堆中给链表动态分配内存。

4.强大但易用的消息机制(Powerful but easy-to-use messaging)
这种情况下利用MessageQ模块来传递消息。
除了Notify通知机制,还可以利用MessageQ来实现更为复杂的核间通信,在这种情况下,只需要配置MultiProc和SharedRegion模块就可以了,而Ipc_start()函数将自动为我们实现上面灰色模块的配置。

最小使用(Minimal use)情况举例
打开CCS自带例程


选中Group,点击运行:


结果分析

1.各核打印:

这段是在main()中出现的结果,每个核都会执行各自的main():
System_printf("main: MultiProc id = %d\n", MultiProc_self());
System_printf("main: MultiProc name = %s\n",
MultiProc_getName(MultiProc_self()));
2.各核注册事件,并表明其反馈函数:
status = Notify_registerEvent(srcProc, INTERRUPT_LINE, EVENTID,
(Notify_FnNotifyCbck)cbFxn, NULL);
核0执行同时释放信号量,在核0释放信号量semHandle之前,其他核都处理等待信号量释放中

核0通过给核1发送事件,触发反馈函数,在反馈函数中semHandle归一,注意这个激活的信号量是在核1中的
status = Notify_sendEvent(dstProc, INTERRUPT_LINE, EVENTID, seq,
TRUE);
激活核1的信号量后,核0打印结果,并等待其信号量的结果,所有核的信号量都初始为0:
System_printf("tsk1_func: Sent request #%d to %s\n", seq,
MultiProc_getName(dstProc));
/* wait forever on a semaphore, semaphore is posted in callback */
Semaphore_pend(semHandle, BIOS_WAIT_FOREVER);
以下是总共八个核,分别执行了NUMLOOPS次(这里设置的是10次)

下一个核信号被激活,开始执行:
/* wait forever on a semaphore, semaphore is posted in callback */
Semaphore_pend(semHandle, BIOS_WAIT_FOREVER); System_printf("tsk1_func: Received request #%d from %s\n", seq,
MultiProc_getName(recvProcId));
同时通过反馈函数将当前核的下一个核激活:
status = Notify_sendEvent(dstProc, INTERRUPT_LINE, EVENTID, seq,
TRUE);
完成发送事件:
System_printf("tsk1_func: Sent request #%d to %s\n", seq,
MultiProc_getName(dstProc));
退出任务循环,同时退出当前核的BIOS:

多核IPC的配置
3.设置同步的核数
4.核间的连接方法Ipc_attach()及Ipc_detach()
Ipc_attach(#coreID),#coreID表示需要连接的核ID号,如Ipc_attach()表示连接核0。
不过需要注意的是:
while(Ipc_attach(#coreID)<)
{
Task_sleep();
}
Ipc_detach()的使用方法同Ipc_attach()是类似的,不过它的功能是解除连接。
主从核之间的通信
2.修改源文件为:
#include <xdc/std.h> /* -----------------------------------XDC.RUNTIME module Headers */
#include <xdc/runtime/System.h> /* ----------------------------------- IPC module Headers */
#include <ti/ipc/MultiProc.h>
#include <ti/ipc/Notify.h>
#include <ti/ipc/Ipc.h>
/* ----------------------------------- BIOS6 module Headers */
#include <ti/sysbios/knl/Semaphore.h>
#include <ti/sysbios/knl/Task.h>
#include <ti/sysbios/BIOS.h> /* ----------------------------------- To get globals from .cfg Header */
#include <xdc/cfg/global.h> #define INTERRUPT_LINE 0 /* Notify event number that the app uses */
#define EVENTID 10 /* Number of times to run the loop */
#define NUMLOOPS 3 UInt32 times = ;
UInt16 recvnumes = ; #define masterProc 0
#define sloverProc1 1
#define sloverProc2 2
#define sloverNum 2 /*
* ======== cbFxn ========
* This function was registered with Notify. It is called when any event is
* sent to this processor.
*/
Void cbFxn(UInt16 procId, UInt16 lineId,
UInt32 eventId, UArg arg, UInt32 payload)
{
/* The payload is a sequence number. */ if(procId!=masterProc) // 主核注册函数
{
recvnumes++; // 接收从核的数目
if(recvnumes==sloverNum) // 当收到全部从核回复的信息
{
recvnumes=;
Semaphore_post(semHandle);
}
}
else
{
times = payload; // 执行次数
Semaphore_post(semHandle);
}
} /*
* ======== tsk0_func ========
* Sends an event to the next processor then pends on a semaphore.
* The semaphore is posted by the callback function.
*/
Void tsk0_func(UArg arg0, UArg arg1)
{
Int i = ;
Int status; if (MultiProc_self() == masterProc)
{
while (i <= NUMLOOPS)
{ /* 这里可以添加主核需要执行的任务代码*/ /* Send an event to the next processor */
status = Notify_sendEvent(sloverProc1, INTERRUPT_LINE, EVENTID, i,
TRUE);
status = Notify_sendEvent(sloverProc2, INTERRUPT_LINE, EVENTID, i,
TRUE); /* Continue until remote side is up */
if (status < )
{
continue;
} System_printf("MasterCore Sent Event to SloverCores in %d\n", i); /* Wait to be released by the cbFxn posting the semaphore */
Semaphore_pend(semHandle, BIOS_WAIT_FOREVER); // 主核等待所有从核完成其工作返回 System_printf("MasterCore Received Event from All SloverCores in %d\n",i); /* increment for next iteration */
i++;
}
}
else {
while (times < NUMLOOPS)
{ /* wait forever on a semaphore, semaphore is posted in callback */
Semaphore_pend(semHandle, BIOS_WAIT_FOREVER); // 等待主核通知开始执行任务 System_printf("SloverCore%d Received Event from MasterCore in %d\n", MultiProc_self(),times); /* 这里可以添加从核执行的任务*/ /* Send an event to the next processor */
status = Notify_sendEvent(masterProc, INTERRUPT_LINE, EVENTID, times,
TRUE);
if (status < ) {
System_abort("sendEvent to MasterCore failed\n");
} System_printf("SloverCore%d sent Event from MasterCore in %d\n", MultiProc_self(),times);
}
} System_printf("Test completed\n");
BIOS_exit();
} /*
* ======== main ========
* Synchronizes all processors (in Ipc_start), calls BIOS_start, and registers
* for an incoming event
*/
Int main(Int argc, Char* argv[])
{
Int status; status = Ipc_start();
if (status < )
{
System_abort("Ipc_start failed\n");
} /*
这里主要根据主核和从核的角色分别添加连接任务:主核同两个从核都有连接,而从核只与主核有链接
在添加核间连接后,分别给核间连接注册事件
*/
if(MultiProc_self()==masterProc)
{
while(Ipc_attach(sloverProc1)){
Task_sleep();
}// 完成从核1的连接
while(Ipc_attach(sloverProc2)){
Task_sleep();
}// 完成从核2的连接 status = Notify_registerEvent(sloverProc1, INTERRUPT_LINE, EVENTID,
(Notify_FnNotifyCbck)cbFxn, NULL);
if (status < ) {
System_abort("Notify_registerEvent for sloverCore1 failed\n");
}// 完成从核1的事件注册 status = Notify_registerEvent(sloverProc2, INTERRUPT_LINE, EVENTID,
(Notify_FnNotifyCbck)cbFxn, NULL);
if (status < ) {
System_abort("Notify_registerEvent for sloverCore2 failed \n");
}// 完成从核2的事件注册 }
else{ while(Ipc_attach(masterProc))
{
Task_sleep();
}// 完成主核0的连接 status = Notify_registerEvent(masterProc, INTERRUPT_LINE, EVENTID,
(Notify_FnNotifyCbck)cbFxn, NULL);
if (status < ) {
System_abort("Notify_registerEvent for masterCore0 failed\n");
}// 完成主核0的事件注册 } BIOS_start(); return ();
}
仿真调试的结果:

从结果上看,当从核分别收到了来自主核的事件时,同时开始任务,当从核任务全部完成后,主核才开始其任务。
IPC的使用的更多相关文章
- Android之使用Bundle进行IPC
一.Bundle进行IPC介绍 四大组件中的三大组件(Activity.Service.Receiver)都是支持在Intent中传递Bundle数据的,由于Bundle实现了Parcelable接口 ...
- Android之使用文件进行IPC
一.文件进行IPC介绍 共享文件也是一种不错的进程间通信方式,两个进程通过读/写同一个文件来交换数据.在Windows上,一个文件如果被加了排斥锁将会导致其他线程无法对其进行访问,包括读写,而由于An ...
- IPC操作时IPC_CREAT和IPC_EXCL选项的说明
IPC(包括消息队列,共享内存,信号量)的xxxget()创建操作时,可以指定IPC_CREAT和IPC_EXCL选项.以共享内存为例:当只有IPC_CREAT选项打开时,不管是否已存在该块共享内存, ...
- TaintDroid剖析之IPC级污点传播
TaintDroid剖析之IPC级污点传播 作者:简行.走位@阿里聚安全 前言 在前三篇文章中我们详细分析了TaintDroid对DVM栈帧的修改,以及它是如何在修改之后的栈帧中实现DVM变量级污点跟 ...
- 为什么使用Binder而不是其他IPC机制
本文搬运自:Advantages of using Binder for IPC in Android 使用Binder而不是其他(Semaphores , Message Queue, PIPES) ...
- 002:IPC与system函数简介
1:IPC名字mq_XXX,sem_XXX,shm_XXX. 消息队列 信号量 共享内存区 <mqueue.h> <semaphore.h> <sys.mman.h> ...
- linux应用程序开发-进程通信(IPC)
IPC why: 1.数据传输 2.资源共享 目的: 3.通知事件 4.进程控制 发展: 1.UNIX进程间通信 2.基于SYStem V 3.POSIX 方式分类: 1.pipe(管道) FIFO( ...
- UNIX:高级环境编程 - 第十五章 IPC:进程间通信
IPC(InterProcess Communication)进程间通信.为啥没有进程间通信,这是因为进程间都是同步的关系,不需要通信. 1.管道 1.1管道特点: (1)半双工的(即数据只能在一个方 ...
- (十三) [终篇] 一起学 Unix 环境高级编程 (APUE) 之 网络 IPC:套接字
. . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...
- Anciroid的IPC机制-Binder概述
在Linux系统中,是以进程为单位分配和管理资源的.出于保护机制,一个进程不能直接访问另一个进程的资源,也就是说,进程之间互相封闭.但是,在一个复杂的应用系统中,通常会使用多个相关的进程来共同完成一项 ...
随机推荐
- 2017-2018-1 20179209《Linux内核原理与分析》第九周作业
理解进程调度时机 进程调度时机 中断处理过程(包括时钟中断.I/O中断.系统调用和异常)中,直接调用schedule(),或者返回用户态时根据need_resched标记调用schedule(): 内 ...
- Smarty模板的逻辑运算符号稍微做一下总结
对Smarty模板的逻辑运算符号稍微做一下总结,以备后用. eq equal : 相等neq not equal:不等于gt greater than:大于lt less th ...
- Ubuntu 14.04 或者16.04开启root账户登录和图形界面登录root时候的报错解决方法
1.打开终端 2.输入sudo vi /usr/share/lightdm/lightdm.conf.d/50-ubuntu.conf 3.添加一行:greeter-show-manual-login ...
- DOM指针
dom节点改变 会自动改变节点的指针 child = formula.firstChild while(child){ next = child.nextSibling; formula.remove ...
- spring项目命名
groupId 一般分为多个段,最简单的分两段,第一段为域,第二段为公司名称.域又分为org.com.cn等等许多, 举个apache公司的tomcat项目例子:这个项目的groupId是org.ap ...
- RabbitMQ之Exchange Direct模式
场景: 生产者发送消息到交换机并指定一个路由key, 消费者队列绑定到交换机时要指定路由key(key匹配就能接受消息,key不匹配就不能接受消息) 例如:我们可以把路由key设置为insert ,那 ...
- eclipse中集成velocity插件
1.打开eclipse,点击help,选择install new software 2.点击add,输入下载地址: http://download.eclipse.org/eclipse/update ...
- HDU5371 Hotaru's problem
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...
- IE和FireFox关于CSS的兼容性
1. [代码][Java]代码 CSS对浏览器的兼容性有时让人很头疼,或许当你了解当中的技巧跟原理,就会觉得也不是难事,从网上收集了IE7,6与Fireofx的兼容性处理技巧并整理了一下.对于web2 ...
- orcal操作锦集
更新时间:update qs_settle_dt_cfg set end_date=to_date('9999-12-31','yyyy-MM-dd');查询时间:select to_char( e ...