EPICS IOC多核运行及测试

一、编译安装方法

1. 编译安装环境
(1)Linux 操作系统
(2)EPICS BASE 3.15 (3.15.1 or later)
(MCoreUtils中使用了一些EPICS BASE 3.15之后才有的函数,例如epicsThreadHookAdd()函数)

2. 下载安装包
https://github.com/epics-modules/MCoreUtils

3. 编译安装生成mcoreutils库

tar -zxvf MCoreUtils-1.2.2.tar.gz /home/dongxw/modules/MCoreUtils-1.2.2
cd /home/dongxw/modules/MCoreUtils-1.2.2
make

二、使用方法

1. 在IOC中引入MCoreUtils
(1)在< path to IOC >/configure/RELEASE文件中,添加MCoreUtils路径:

MCOREUTILS = /home/dongxw/modules/MCoreUtils-1.2.2

(2)在< path to IOC >/< IOC >APP/src/Makefile文件中,添加MCoreUtils库和dbd:

...
<IOC>_DBD += mcoreutils.dbd
...
<IOC>_LIBS += mcoreutils
...

(3)编译运行IOC
注意:MCoreUtils 仅适用于Linux系统,因此只有Linux下编译运行的IOC可以执行上述操作,从而使用MCoreUtils。

2. 在文件中定义线程规则
可以预先设置线程规则文件:
(1) /etc/rtrules文件
(2)$HOME下的EPICS_MCORE_USERCONFIG定义的文件名或.rtrules文件
文件中线程规则定义格式为:

name:policy:priority:affinity:pattern

通过epicsThreadOnce()1和 epicsThreadHookAdd()函数2,在任何epicsThreadOnce()函数之前完成以下操作:读取线程规则文件后,生成threadRules表;令每个线程运行前都根据threadRules表中与id名字对应的规则修改id的线程规则。

3. 执行iocsh命令对线程规则进行操作
shellCommands.c 和 mcoreutils.dbd 文件结合,将一些函数注册为可在iocsh下执行的命令。这些命令在IOC启动时即注册入可执行命令库3,可以在 st.cmd 文件中执行这些命令,也可在 “epics>”命令行执行这些命令。
例如,IOC启动后,在iocsh下查看可执行命令库:

epics> help
...
iocRun          iocshCmd        iocshLoad       iocshRun        mcoreMLock
mcoreMUnlock    mcoreThreadModify               mcoreThreadRuleAdd
mcoreThreadRuleDelete           mcoreThreadRulesShow
mcoreThreadShow mcoreThreadShowAll              on              pft
...

可以看到,关于 MCoreUtils 的一些命令也在其中。
例如,使用mcoreThreadShow命令来查看errlog线程的当前优先级状态:

epics> mcoreThreadShow errlog
mcoreThreadShow errlog
            NAME       EPICS ID   LWP ID   OSIPRI  OSSPRI  STATE  POLICY CPUSET
          errlog       0x73f480    15427     10       0       OK   OTHER 0-3

也可以更改一些线程的优先级:

epics> mcoreThreadShow scan-10
mcoreThreadShow scan-10
            NAME       EPICS ID   LWP ID   OSIPRI  OSSPRI  STATE  POLICY CPUSET
         scan-10       0x8c4db0    15443     50       0       OK   OTHER 0-3
epics> mcoreThreadModify scan-10 * 40 0   # 更改OSIPRI为40,CPU亲和性为0号CPU
mcoreThreadModify scan-10 * 40 0
epics> mcoreThreadShow scan-10
mcoreThreadShow scan-10
            NAME       EPICS ID   LWP ID   OSIPRI  OSSPRI  STATE  POLICY CPUSET
         scan-10       0x8c4db0    15443     40       0       OK   OTHER 0

EPICS IOC多核运行及测试

三、多核运行测试

编写脚本对IOC多线程的多核运行情况进行测试:

#!/bin/bash
# this script can have one or two inputs:
# $1 is for the name of IOC
# $2 is whether or not to use MCoreUtils. If not, input $2 as "no". If yes, no need to input anything as $2.


ioc=$1
using_mcu=$2
pid=`ps -ef|grep st.cmd|grep $ioc | awk '{print $2}'`
file=`[ ${using_mcu} ] && echo ${using_mcu}_`multicore.log
echo "${ioc}'s pid is:$pid \nwritting into $file"


ps -o pid,tid,psr -p $pid -m > $file

attend_psr()
{
        psr=$@
        line=1
        for ppsr in $psr
        do
                if [ $ppsr != "PSR" ]
                then
                        ppsr="  $ppsr"   # 列对齐
                fi
                sed -i ''"$line"' s@$@ '"$ppsr"'@g' $file   # 在每行末尾添加新数据
                line=$((line+1))
        done
}

while [ 1 ]
do
        sleep 1
        psr=`ps -o psr -p $pid -m`   # 查询IOC多核运行情况
        attend_psr $psr   # 在log文件中新增一列数据
done

【参考文章】

Linux上如何查看某个进程的线程
Shell ps常用组合查看线程命令
判断Linux进程在哪个CPU核运行的方法
Linux多线程之pthread_setschedparam
C语言–Linux多线程pthread
如何获取进程的线程id?------说说gettid与pthread_self的区别
CPU亲和性(affinity)sched_setaffinity() 和 sched_getaffinity() CPU_SET()与CPU_ZERO()
linux进程、线程与cpu的亲和性(affinity)
sed在shell脚本中引用变量
sed命令简介及在sed命令中使用变量的方法
linux 搜索一个字符串再哪个文件中
Linux在文件中查找字符串
C语言正则表达式详解 regcomp() regexec() regfree()用法详解


  1. 在epics用户手册中对 epicsThreadOnce 函数描述如下:
    “This is used as follows:

     void myInitFunc(void * arg)
     {
     ...
     }
     epicsThreadOnceId onceFlag = EPICS_THREAD_ONCE_INIT;
     ...
     epicsThreadOnce(&onceFlag,myInitFunc,(void *)myParm);
    

    For each unique epicsThreadOnceId, epicsThreadOnce guarantees

    1. myInitFunc is called only once.
    2. myInitFunc completes before any epicsThreadOnce call completes.
      Note that myInitFunc must not call epicsThreadOnce with the same onceId.”
    ↩︎
  2. 在epics用户手册中对 epicsThreadHookAdd 函数描述如下:
    “Register a routine to be called by every new thread before the thread function gets run. Hook routines will often register a thread exit routine with epicsAtThreadExit to release thread-specific resources they have allocated.” ↩︎

  3. 这种函数注册机制在epics用户手册中描述如下:
    “ 18.3.3 Registrar Command Registration
    Commands are normally registered with the IOC shell in a registrar function. The application’s database description file
    uses the registrar keyword to specify a function which will be called from the EPICS initialization code during the
    application startup process. This function then calls iocshRegister to register its commands with the iocsh.
    … ” ↩︎

上一篇:控制反转/依赖注入的理解


下一篇:Spring IOC_容器设计原理