RTLevel default 0 (aus)

Workdirectory prüfen vor dem Wechseln
Optimierung -OO entfernt
_setuprt(...) um ksoftirqd und ktimersoftd auf höhere Prioritäten zu ziehen
Python PLC Programm kann max auf Prio RR 1 laufen
This commit is contained in:
2017-09-20 18:12:44 +02:00
parent 6b8894a66e
commit 7d0234a1b2
8 changed files with 145 additions and 32 deletions

View File

@@ -8,7 +8,7 @@ plcuid = 1000
plcgid = 1000 plcgid = 1000
plcslave = 0 plcslave = 0
pythonversion = 3 pythonversion = 3
rtlevel = 1 rtlevel = 0
xmlrpc = 0 xmlrpc = 0
zeroonerror = 0 zeroonerror = 0
zeroonexit = 0 zeroonexit = 0

View File

@@ -23,6 +23,9 @@ Classes</h3>
Functions</h3> Functions</h3>
<table> <table>
<tr> <tr>
<td><a style="color:#0000FF" href="#_setuprt">_setuprt</a></td>
<td>Konfiguriert Programm fuer den RT-Scheduler.</td>
</tr><tr>
<td><a style="color:#0000FF" href="#_zeroprocimg">_zeroprocimg</a></td> <td><a style="color:#0000FF" href="#_zeroprocimg">_zeroprocimg</a></td>
<td>Setzt Prozessabbild auf NULL.</td> <td>Setzt Prozessabbild auf NULL.</td>
</tr><tr> </tr><tr>
@@ -34,6 +37,24 @@ Functions</h3>
</tr> </tr>
</table> </table>
<hr /><hr /> <hr /><hr />
<a NAME="_setuprt" ID="_setuprt"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_setuprt</h2>
<b>_setuprt</b>(<i>pid, evt_exit</i>)
<p>
Konfiguriert Programm fuer den RT-Scheduler.
</p><dl>
<dt><i>pid</i></dt>
<dd>
PID, der angehoben werden soll
</dd>
</dl><dl>
<dt>Returns:</dt>
<dd>
None
</dd>
</dl>
<div align="right"><a style="color:#0000FF" href="#top">Up</a></div>
<hr /><hr />
<a NAME="_zeroprocimg" ID="_zeroprocimg"></a> <a NAME="_zeroprocimg" ID="_zeroprocimg"></a>
<h2 style="background-color:#FFFFFF;color:#0000FF">_zeroprocimg</h2> <h2 style="background-color:#FFFFFF;color:#0000FF">_zeroprocimg</h2>
<b>_zeroprocimg</b>(<i></i>) <b>_zeroprocimg</b>(<i></i>)

View File

@@ -24,6 +24,7 @@ procimgserver.ProcimgServer.start?4()
procimgserver.ProcimgServer.stop?4() procimgserver.ProcimgServer.stop?4()
procimgserver.ProcimgServer.values?4() procimgserver.ProcimgServer.values?4()
procimgserver.ProcimgServer?1(xmlserver, aclmode) procimgserver.ProcimgServer?1(xmlserver, aclmode)
proginit._setuprt?5(pid, evt_exit)
proginit._zeroprocimg?5() proginit._zeroprocimg?5()
proginit.cleanup?4() proginit.cleanup?4()
proginit.configure?4() proginit.configure?4()

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Project SYSTEM "Project-5.1.dtd"> <!DOCTYPE Project SYSTEM "Project-5.1.dtd">
<!-- eric project file for project revpipyload --> <!-- eric project file for project revpipyload -->
<!-- Saved: 2017-09-17, 11:21:23 --> <!-- Saved: 2017-09-20, 18:10:38 -->
<!-- Copyright (C) 2017 Sven Sager, akira@narux.de --> <!-- Copyright (C) 2017 Sven Sager, akira@narux.de -->
<Project version="5.1"> <Project version="5.1">
<Language>en_US</Language> <Language>en_US</Language>
@@ -9,7 +9,7 @@
<ProgLanguage mixed="0">Python3</ProgLanguage> <ProgLanguage mixed="0">Python3</ProgLanguage>
<ProjectType>Console</ProjectType> <ProjectType>Console</ProjectType>
<Description>Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.</Description> <Description>Dieser Loader wird über das Init-System geladen und führt das angegebene Pythonprogramm aus. Es ist für den RevolutionPi gedacht um automatisch das SPS-Programm zu starten.</Description>
<Version>0.4.3</Version> <Version>0.4.6</Version>
<Author>Sven Sager</Author> <Author>Sven Sager</Author>
<Email>akira@narux.de</Email> <Email>akira@narux.de</Email>
<Eol index="1"/> <Eol index="1"/>

View File

@@ -11,6 +11,7 @@ import proginit
import shlex import shlex
import subprocess import subprocess
from logsystem import PipeLogwriter from logsystem import PipeLogwriter
from proginit import _setuprt
from sys import stdout as sysstdout from sys import stdout as sysstdout
from threading import Event, Thread from threading import Event, Thread
from time import sleep, asctime from time import sleep, asctime
@@ -41,7 +42,7 @@ class RevPiPlc(Thread):
self.exitcode = None self.exitcode = None
self.gid = 65534 self.gid = 65534
self.uid = 65534 self.uid = 65534
self.rtlevel = 1 self.rtlevel = 0
self.zeroonerror = False self.zeroonerror = False
self.zeroonexit = False self.zeroonexit = False
@@ -104,8 +105,16 @@ class RevPiPlc(Thread):
"""Fuehrt PLC-Programm aus und ueberwacht es.""" """Fuehrt PLC-Programm aus und ueberwacht es."""
proginit.logger.debug("enter RevPiPlc.run()") proginit.logger.debug("enter RevPiPlc.run()")
# LogWriter starten und Logausgaben schreiben
if self._plw is not None:
self._plw.logline("-" * 55)
self._plw.logline("plc: {} started: {}".format(
os.path.basename(self._program), asctime()
))
self._plw.start()
# Befehlstliste aufbauen # Befehlstliste aufbauen
lst_proc = shlex.split("/usr/bin/env {} -OO -u {} {}".format( lst_proc = shlex.split("/usr/bin/env {} -u {} {}".format(
"python2" if self._pversion == 2 else "python3", "python2" if self._pversion == 2 else "python3",
self._program, self._program,
self._arguments self._arguments
@@ -115,29 +124,13 @@ class RevPiPlc(Thread):
proginit.logger.info("start plc program {}".format(self._program)) proginit.logger.info("start plc program {}".format(self._program))
self._procplc = self._spopen(lst_proc) self._procplc = self._spopen(lst_proc)
# RealTime Scheduler nutzen # RealTime Scheduler nutzen nach 5 Sekunden Programmvorlauf
if self.rtlevel > 0 and self._procplc.poll() is None: if self.rtlevel > 0 \
proginit.logger.info( and not self._evt_exit.wait(5) \
"set scheduler profile of pid {}".format(self._procplc.pid) and self._procplc.poll() is None:
) _setuprt(self._procplc.pid, self._evt_exit)
ec = os.system("/usr/bin/env chrt -p {} {}".format(
20 if self.rtlevel == 2 else 1,
self._procplc.pid
))
if ec != 0:
proginit.logger.error(
"could not set scheduler profile of pid {}"
"".format(self._procplc.pid)
)
# LogWriter starten und Logausgaben schreiben
if self._plw is not None:
self._plw.logline("-" * 55)
self._plw.logline("plc: {} started: {}".format(
os.path.basename(self._program), asctime()
))
self._plw.start()
# Überwachung starten
while not self._evt_exit.is_set(): while not self._evt_exit.is_set():
# Auswerten # Auswerten
@@ -179,7 +172,7 @@ class RevPiPlc(Thread):
else: else:
break break
self._evt_exit.wait(1) self._evt_exit.wait(0.5)
if self._plw is not None: if self._plw is not None:
self._plw.logline("-" * 55) self._plw.logline("-" * 55)

View File

@@ -10,6 +10,7 @@ import logging
import os import os
import sys import sys
from argparse import ArgumentParser from argparse import ArgumentParser
from subprocess import Popen, PIPE
forked = False forked = False
globalconffile = None globalconffile = None
@@ -22,6 +23,99 @@ rapcatalog = None
startdir = None startdir = None
def _setuprt(pid, evt_exit):
"""Konfiguriert Programm fuer den RT-Scheduler.
@param pid PID, der angehoben werden soll
@return None"""
if logger is not None:
logger.debug("enter _setuprt()")
dict_change = {
"ksoftirqd/0,ksoftirqd/1,ksoftirqd/2,ksoftirqd/3": 10,
"ktimersoftd/0,ktimersoftd/1,ktimersoftd/2,ktimersoftd/3": 20
}
for ps_change in dict_change:
# pid und prio ermitteln
kpidps = Popen([
"/bin/ps", "-o", "pid=,rtprio=", "-C", ps_change
], bufsize=1, stdout=PIPE)
# Timeout nachbilden da in Python 3.2 nicht vorhanden
count = 10
while kpidps.poll() is None:
count -= 1
if count == 0:
kpidps.kill()
if logger is not None:
logger.error(
"ps timeout to get rt prio info - no rt active"
)
return None
evt_exit.wait(0.5)
if evt_exit.is_set():
return None
try:
kpiddat = kpidps.communicate()[0]
lst_kpids = kpiddat.split()
except:
kpidps.kill()
if logger is not None:
logger.error(
"can not get pid and prio - no rt active"
)
return None
while len(lst_kpids) > 0:
# Elemente paarweise übernehmen
kpid = lst_kpids.pop(0)
kprio = lst_kpids.pop(0)
# Daten prüfen
if not kpid.isdigit():
if logger is not None:
logger.error(
"pid={} and prio={} are not valid - no rt active"
"".format(kpid, kprio)
)
return None
kpid = int(kpid)
# RTPrio ermitteln
if kprio.isdigit():
kprio = int(kprio)
else:
kprio = 0
if kprio < 10:
# Profile anpassen
ec = os.system("/usr/bin/env chrt -fp {} {}".format(
dict_change[ps_change], kpid
))
if ec != 0:
if logger is not None:
logger.error(
"could not adjust scheduler - no rt active"
)
return None
# SCHED_RR für pid setzen
if logger is not None:
logger.info("set scheduler profile of pid {}".format(pid))
ec = os.system("/usr/bin/env chrt -p 1 {}".format(pid))
if ec != 0 and logger is not None:
logger.error(
"could not set scheduler profile of pid {}"
"".format(pid)
)
if logger is not None:
logger.debug("leave _setuprt()")
def _zeroprocimg(): def _zeroprocimg():
"""Setzt Prozessabbild auf NULL.""" """Setzt Prozessabbild auf NULL."""
procimg = "/dev/piControl0" if pargs is None else pargs.procimg procimg = "/dev/piControl0" if pargs is None else pargs.procimg

View File

@@ -49,7 +49,7 @@ from time import asctime
from xmlrpc.client import Binary from xmlrpc.client import Binary
from xmlrpc.server import SimpleXMLRPCServer from xmlrpc.server import SimpleXMLRPCServer
pyloadversion = "0.4.5" pyloadversion = "0.4.6"
class RevPiPyLoad(): class RevPiPyLoad():
@@ -124,7 +124,7 @@ class RevPiPyLoad():
self.pythonver = \ self.pythonver = \
int(self.globalconfig["DEFAULT"].get("pythonversion", 3)) int(self.globalconfig["DEFAULT"].get("pythonversion", 3))
self.rtlevel = \ self.rtlevel = \
int(self.globalconfig["DEFAULT"].get("rtlevel", 1)) int(self.globalconfig["DEFAULT"].get("rtlevel", 0))
self.xmlrpc = \ self.xmlrpc = \
int(self.globalconfig["DEFAULT"].get("xmlrpc", 0)) int(self.globalconfig["DEFAULT"].get("xmlrpc", 0))
self.zeroonerror = \ self.zeroonerror = \
@@ -133,6 +133,10 @@ class RevPiPyLoad():
int(self.globalconfig["DEFAULT"].get("zeroonexit", 1)) int(self.globalconfig["DEFAULT"].get("zeroonexit", 1))
# Workdirectory wechseln # Workdirectory wechseln
if not os.access(self.plcworkdir, os.R_OK | os.W_OK | os.X_OK):
raise ValueError(
"can not access plcworkdir '{}'".format(self.plcworkdir)
)
os.chdir(self.plcworkdir) os.chdir(self.plcworkdir)
# PLC Thread konfigurieren # PLC Thread konfigurieren
@@ -569,7 +573,7 @@ class RevPiPyLoad():
"plcarguments": ".*", "plcarguments": ".*",
"plcslave": "[01]", "plcslave": "[01]",
"pythonversion": "[23]", "pythonversion": "[23]",
"rtlevel": "[0-2]", "rtlevel": "[0-1]",
"xmlrpc": "[0-3]", "xmlrpc": "[0-3]",
"zeroonerror": "[01]", "zeroonerror": "[01]",
"zeroonexit": "[01]" "zeroonexit": "[01]"

View File

@@ -27,7 +27,7 @@ setup(
license="LGPLv3", license="LGPLv3",
name="revpipyload", name="revpipyload",
version="0.4.5", version="0.4.6",
scripts=["data/revpipyload"], scripts=["data/revpipyload"],