I-RT-HOME

  1. Einführung

  2. Engineering von Realzeitsystemen

  3. Kleiner Betriebssystemkern

  4. Allgemeine Kriterien für sichere Systeme

  5. POSIX

    1. POSIX conformance/compliance allgemein

    2. POSIX conformance/compliance speziell

  6. Wichtige RT-OS-Firmen und RT-OSs

  7. Ein RT-OS am Beispiel von RTAI

  8. Testfragen


I-RT REALZEITSYSTEME WS0304
VL11-12: Realzeitsysteme mit RTAI I-II

    Achtung : Skript gibt den mündlichen Vortrag nur teilweise wieder !!!
	Achtung : Arbeiten am Skript vorläufig abgeschlossen, wenngleich noch unvollständig !!!
                        

AUTHOR: Gerd Döben-Henisch
DATE OF FIRST GENERATION: September-16, 2003
DATE OF LAST CHANGE: Jan-25, 2004, 23:10h
EMAIL: Gerd Döben-Henisch



1. Einführung

Bei den bisherigen Vorlesungen lag der Schwerpunkt auf der Einführung einiger grundlegender Begriffe und Fragen der Modellierung von Realzeit-Poblemen. In den beiden letzten Vorlesung soll die Frage des Designs von Realzeitsystemen zumindest angerissen werden. Dabei zeigt sich einerseits nochmals die Besonderheit von Realzeit-Systemen gegenüber Nichtrealzeit-Systemen, wie auch der Tatbestand, dass die Anforderungen an die Realisierung von Realzeitsystemen dramatisch höher sind als bei Nichtrealzeit-Systemen. Ein Nebeneffekt dieses Tatbestandes ist der, dass es sich nur Firmen ab einer bestimmten Grösse überhaupt leisten können, die notwendigen Anforderungen --konkretisiert in Standards und vorgeschriebenen Zertifizierungen-- einzulösen.

Im folgenden sollen zumindest die Umrisse eines Realzeitdesigns angedeutet werden, abgeschlossen durch ein erstes kleines Beispiel eines konkreten Systems anhand des RTAI.


START



2. Engineering von Realzeitsystemen

Das Ziel des Designs ist es im allgemeinen, das zuvor modellierte Problem in ein konkretes System zu überführen, das sämtliche Anforderungen aus der Problemstellung löst. Dieses Überführung in ein konkretes System muss dabei in unterschiedlichem Umfang konkreten Umständen Rechnung tragen, die sich aus notwendigen Realisierungsbedinungen (wie z.B. Hardware, vorhandene Software, Umgebungseigenschaften) ergeben. Dazu gehören u.a. auch verabschiedete Standards, die bestimmte Asoekte eines Einsatzes des Systems regulieren.

Während sich das Softwareengineering von Nichtrealzeit-Systemen meistens auf die konzeptuelle Modellierung von Software konzentrieren kann, ist im Falle von Realzeitsystemen die Einbeziehung der Hardware und ihrer Eigenschaften fast unausweichlich; nur wenn die benutzte Hardware nachweislich bestimmte Anforderungen erfüllt, kann auch die Software bestimmte Anforderungen erfüllen. Deswegen bedeutet das Engineering von Realzeitsystemen in der Regel nicht nur das Engineering von Software (also Software-Engineering (SWE)), sondern meist auch zugleich das Engineering der Harware. Man sollte daher vielleicht direkt von Real Time Engineering (RTE) sprechen.

Die beiden nachfolgenden Schaubilder zeigen drüberhinaus auch noch weitere Besonderheiten:



RTswe-2a

SWE mit Nicht-RT-Systemen





RTswe-2b

SWE mit RT-Systemen



  1. Während das SWE heute meist objektorientiert (OO) ist und als zentrale Konzepte Klassen mit Attributen und Methoden identifiziert, die miteinadner vernetzt werden, betrachtet das RTE primär Systeme, deren Ressourcen von Tasks beansprucht werden, die bestimmte Zeitintervalle bedienen müssen.


  2. Da die im OO-SWE heute meist benutzen UML-Diagramme zur Repräsentierung von Klassen und deren Interaktionen nicht ausreichen, um die wichtigen Eigenschaften von Realzeitsystemen zu modellieren, findet man im Rahmen des RTE ganz andere konzeptuelle Mittel (Technische Tabellen, Taskgraphen, usw.), mit denen man die Modellierung vornimmt.


  3. Selbst bei dem Einsatz von sogeannten Case-Tools im Rahmen des OO-SWE bleibt eine nicht geringe Menge an 'Wissen' ausserhalb der Modellierung, da die Modellierung nur die Repräsentation von allgemeinen Strukturen erlaubt. Dies hat zur Folge, dass bei der automatischen Generierung des Kodes die Rümpfe der beteiligten Methoden --sofern es sich nicht um von einem Hersteller 'vorfabrizierte Methoden handelt-- 'leer' sind; d.h. es bedarf abschliessend noch der 'Füllung' all dieser 'Modellierungslöcher'.


  4. Im Falle des RTE ist dies in keiner Weise akzeptabel, d.h. die Modellierung muss vollständig sein, andernfalls können die notwendigen Garantien für das angeforderte RT-System nicht abgegeben werden.


  5. Im Falle des RTE muss von den benutzten Architekturen auf jeden Fall gefordert werden, dass sie safety critical sind und dass dieser Tatbestand zertifiziert ist.


Diese spezifischen Anforderungen an ein RTE sollen im folgenen kurz weiter erläutert werden. Anschliessend wird ein Beispiel repräsentiert.


START



3. Kleiner Betriebssystemkern

Dieser Letzte Tatbestand, dass RT-Systeme zertifizierbar sein müssen, hat weitreichende Konsequenzen (siehe dazu die interessanten Überlegungen in einem Whitepaper der Firma Lynuxworks vom September 2003) Meistens entsteht die Forderung einer Zertifizierung bei staatlichen Projekten, aber auch z.B. in der privaten Luftfahrt. Diese soll sowohl die Zuverlässigkeit wie auch die Sicherheit nach bestimmten Kriterien sicher stellen

Wie Untersuchungen der amerikanischen Regierung aufzeigten, scheiterten alle Projekte, die nicht in der Lage waren, die Aufgabenstellung sehr weitgehend auf kleine Module herunterzubrechen; ein 'zu grosser' Betriebssysmkern ist nicht zertifizierbar. Erst solche Systeme, die einen separierten kleinen Kern haben, dem man nach Bedarf beliebig Module zuschalten kann, lassen sich zertifizieren.

Diese Idee eines kleinen, sicheren Kernels gehen zurück auf Arbeiten von John RUSHBY, der 1989 in einem Artikel "Kernels for Safety?" schreibt: Work on "secure" systems has evolved an approach to systems design based on the idea of a "security kernel": a small component of the total system whose correctness is sufficient to ensure the security of the system as a whole. The attraction is that the expensive and difficult techniques needed to guarantee correct behavior need only be applied to the relatively small security kernel--yet the benefit will apply to the complete system. It is interesting and potentially rewarding, therefore, to enquire whether the security kernel approach can be extended to apply to properties other than security.

Die beiden zentralen Aufgaben, die solch ein Kern leisten muss, sind die Ermöglichung des Informationsflusses und die Datenseparation. Alles andere, kann auf andere Module ausgelagert werden. Man spricht hier auch vom Kernelspace und dem Userspace; im Kernelspace sind nur die zentralen Aufgaben lokalisiert, alles andere befindet sich im Userspace.



smallKernel

Bild: Beispiel eines kleinen Kernels (übernommen von LynuxWorks)



Diese Architektur erlaubt es, die Sicherheits-Regeln auf höchster Ebene --spricht: im Kenel-- so zu etablieren, dass sämtliche Module, die auf den Kern zugreifen, diese Sicherheits-Regeln beachten müssen. Man spricht hier von einer Mehr-Ebenen-Sicherheit ('Multi Level Security (MLS)').


START



4. Allgemeine Kriterien für sichere Systeme

Natürlich stellt sich die Frage, welches denn die Kriterien sind, nach denen ein System als sicheres System einzustufen ist.

Eine mögliche Antwort bieten die gemeinsamen Kriterien/ Common Criteria (CC), zu denen das BSI - Bundesamt für Sicherheit und Informationstechnik schreibt: "Gemeinsame Kriterien für die Prüfung und Bewertung der Sicherheit von Informationstechnik/ Common Criteria for Information Technology Security Evaluation (CC), Version 2.0" sind Ende im Mai 1998 unter Beteiligung Deutschlands, Frankreichs, Großbritanniens, Kanadas, der Niederlande und der USA abschließend fertiggestellt worden. Sie sind für die Bewertung der Sicherheitseigenschaften praktisch aller informationstechnischen Produkte und Systeme geeignet. Das Bundesamt für Sicherheit in der Informationstechnik (BSI) hat dabei die Rolle des deutschen Partners übernommen und bei der Erarbeitung der Kriterien aktiv mitgewirkt. Die CC 2.1 sind durch die Internationale Standardisierungsorganisation (ISO) unter der Nummer 15408 ein internationaler Standard geworden. Die wenigen nichttechnischen Änderungen, die durch den Standardisierungsprozess der ISO notwendig geworden sind, wurden in der CC Version 2.1 durchgeführt. Die Version 2.1 wurde wie die Version 2.0 der Common Criteria gemäß BSI-Zertifizierungsverordnung im Bundesanzeiger offiziell bekannt gemacht. Erste Entwürfe einer gemeinsamen Evaluationsmethodologie (Common Methodology for Information Security Evaluation CEM), die der Entwicklung eines gemeinsamen Konzepts und einer abgestimmten Methodik für die Evaluierung auf Grundlage der CC dienen, sind entwickelt und veröffentlicht worden. (Siehe auch NIST: Common Criteria)

.

In den USA spielt daneben der Standard DO-178B der Federal Aviation Administration (FAA) zur Zertifizierung von Flugsystemen eine grosse Rolle. Für die Beziehung zwischen den Common Criteria (CC) und DO-178B gilt allgemein: "Common Criteria defines seven different levels called Evaluated Assurance Level (EAL). These levels are numbered from 1 to 7 with one being the lowest level and 7 being the highest. For the reader familiar with the DoD Orange Book (TCSEC 5200.28), EAL 7 is equivalent to an A system, 6 is B3, etc. (While Common Criteria does not require the use of EALs, they are generally accepted as the best means for defining the security level of target of evaluation (TOE). A TOE can be an OS, a firewall device, etc.)"

Dabei ist zu bachten, dass die FAA normalerweise keine einzelnen Komponenten zertifiziert, sondern nur komplette Systeme. Allerdings gibt es die Möglichkeit, Software als Removable Software Component [RSC] innerhalb eines zertifizioerten Systems zu behandeln und zu zertifizieren.

In einer Untersuchung von J. Alves-Foss, B. Rinker and C. Taylor (2002) findet sich zusätzliche charakterisierung des Verhältnisses von CC und DO-178B: "... software developed to DO-178B Level A standards will map closely to either an EAL 4 or 5 with some additional work. The additional work is to satisfy objectives generally not covered by DO-178B but they may be covered via good engineering practices. Examples include delivery mechanisms and vulnerability assessments. A DO-178B kernel's space partitioning generally will solve most of the problems related to information flow since there is no sharing of memory between partitions. This is generally done to protect partitions from one another. In addition, the time partitioning used in DO-178B kernels will prevent system resources from being monopolized by a single partition, often a concern for secure systems. These two features provide most of what will be needed in a secure kernel.

Es ist allgemeine Überzeugung, dass zur Erreichung eines EAL 7 Rating --vorausgesetzt der Kernel ist sehr klein und umfasst nur die minimalen Funktionalitäten für Informationsfluss und Datentrennung-- formale Spezifikationsmethoden notwendig sind.

Ein Beispiel für ein RT-System, das von der FAA für den DO-178B Level A standard zertifiziert ist LynxOS-178 von LynuxWorks.

Neben den Standards CC und DO-178B sei hier noch erwähnt POSIX und ISO9001


START



5. POSIX

Die strategie des kleinen Betriebssystem-Kerns löst zwar das Problem für den Kern selbst, lässt abr dann zunächst offen, wie man diesen kleinen Kern mit den übrigen Modulen verbindet. Ein naheliegender Ansatz betseht hier darin, die Zugriffe auf den Kern soweit wie möglich zu standardisieren. Dieser anspruch wird z.B. von POSIX eingelöst. POSIX ist ein Acronym für Portable Operating System Interface und ist eng mit der Geschichte von UNIX verbunden ( bis hin zum heutigen Linux). Die aktuelle Version des POSIX-Standards findet man unter 2003 Edition of IEEE Std 1003.1 (known as "POSIX.1".

POSIX wurde zusammen entwickelt von IEEE und The Open Group. Es ist zugleich ein IEEE Standard und ein ISO/IEC Standard sowie ein Open Group Technical Standard.

Die Open Group schreibt dazu: "Conceptually, this standard describes a set of fundamental services needed for the efficient construction of application programs. Access to these services has been provided by defining an interface, using the C programming language, a command interpreter, and common utility programs that establish standard semantics and syntax. Since this interface enables application writers to write portable applications-it was developed with that goal in mind-it has been designated POSIX,1 an acronym for Portable Operating System Interface."

"Although originated to refer to the original IEEE Std 1003.1-1988, the name POSIX more correctly refers to a family of related standards: IEEE Std 1003.n and the parts of ISO/IEC 9945. In earlier editions of the IEEE standard, the term POSIX was used as a synonym for IEEE Std 1003.1-1988. A preferred term, POSIX.1, emerged. This maintained the advantages of readability of the symbol ``POSIX'' without being ambiguous with the POSIX family of standards."

"Several principles guided the development of this standard:

The developers of this standard endeavored to make all specified functions implementable across a wide range of existing and potential systems, including:

  1. All of the current major systems that are ultimately derived from the original UNIX system code (Version 7 or later)

  2. Compatible systems that are not derived from the original UNIX system code

  3. Emulations hosted on entirely different operating systems

  4. Networked systems

  5. Distributed systems

  6. Systems running on a broad range of hardware

No direct references to this goal appear in this standard, but some results of it are mentioned in the Rationale volume."


Hier ein grober Überblick über die Struktur des POSIX-Standards. Für Details siehe die das Dokument selbst:

  1. POSIX.1: POSIX core services (the feature set usually found in UNIX® operating systems)

  2. POSIX.1b: real-time extensions

  3. POSIX.1c: thread extensions

POSIX.1 Core Services (incorporates Standard ANSI C)

POSIX.1b Real-time extensions

POSIX.1c Threads extensions


START



5.1 POSIX conformance/compliance allgemein

POSIX conformance means that the POSIX.1 standard is supported in its entirety.

Certified POSIX conformance exists when conformance is certified by an accredited, independent certification authority.

POSIX compliance means that documentation is available that shows which POSIX features are supported and which are not.

Als wesentliche Eigenschaften für POSIX-konforme Systeme gilt:

  1. Eigener Namensbereich mit separater Symboltabelle

  2. Unterstützung für den fork() call

  3. Unterscheidung zwischen threads und Prozessen

  4. Die Verfügbarkeit von Signalen

Ein konkretes Beispiel für ein POSIX1.b+c zertifiziertes System ist LynxOS von LynuxWorks.



START



5.2 POSIX Conformance/Compliance speziell

Für die nachfolgenden Erläuterungen zu einzelnen Aspekten der POSIX-Konformität siehe folgenden Artikel von LynuxWorks :

As processor technology advancement increases the speed of the microprocessor, more programs can be executed on a single processor. These additional programs increase the complexity of the system and the number of bugs that slip into the system. A single bug that can corrupt unrelated tasks unchecked, can easily leave a trail of missed deadlines and "red ink" from man-months in product debug and system test. The bugs resulting elusive system crashes may not reappear until it is too late and the product is deployed. A further addition to the burden is that, the cost of implementing a "fix" in an embedded system increases exponentially after the product is deployed.

The microprocessor MMU can be programmed to protect user tasks and the kernel from accidental corruption with minimal impact to overall system performance. Using multiple protected address spaces insulates the user tasks and terminates only the offending task on an invalid memory reference. This allows the other programs to continue processing and protects the overall system from a catastrophic system crash. Then, the running system can perform a graceful recovery from the terminated task, and optionally log the footprint for later debugging. To use this state-of-the-art capability in real-time embedded systems, two choices must be made early in the project specification. First, choose a processor that has an on-chip MMU. Second, choose an operating system that fully supports the MMU. These two choices just might give you a good night sleep when your product is deployed.

fork()

Fork() calls are scattered throughout Unix/Linux code. To support fork(), an operating system must first support the concept of parent-child relationships between processes. If fork() and other common POSIX.1 calls are not supported, the vast majority of your Unix/Linux code will not port to that operating system without major rewrites. Understanding fork()

The fork() system call creates a new process called a child. The original process is called the parent, and the child is a near-exact copy of the parent. The child's run time is set to zero and file locks are not inherited.

The child has its own process ID and its own copy of the parent's file descriptors.

A parent process can recover the exit status of a child using the wait() or waitpid() function.



fork

Figure: fork()



Threads versus Processes

An important POSIX concept is the distinction between "threads" and "processes." For inter-process communications, kernel services are required.

Threads are schedulable entities that run within a process. Each process will have one main thread, and it may also have several more threads which share the address space of the process invoked via pthread_create(). A POSIX system call will refer to a process ID or to a thread ID?these IDs are not interchangeable

.

Note that some operating systems simply refer to "tasks" instead of distinguishing between "threads" and "processes." Such an operating system probably does not support the POSIX standard, and would not be able to run calls which refer to a process (such as signals). How threads work



threads

Figure: threads



Signals

Signals are integral to any Unix® or Linux® application and are part of the POSIX.1 standard.

A signal is automatically sent to the parent when a child process terminates (SIGCHLD). Signals are also used for many other synchronous and asynchronous notifications, such as: waking a process when a wait call such as pause(), alarm(), or sleep() is performed (SIGALRM); or informing a process that it has issued a memory violation (SIGSEGV).

Signals in POSIX are quite powerful. Each thread can block incoming signals on a per-signal basis, define signal handlers for each signal it might receive, and queue signals (in the case of a real-time signal). Standard Unix POSIX signals do not guarantee delivery. Furthermore, POSIX signals are not queueable nor can they carry any information beyond the signal number itself.

POSIX.1b, supported fully by the LynxOS RTOS, improves this situation. POSIX.1b specifies real-time signals (a minimum of 8 are required) SIGRTMIN through SIGRTMAX to provide these capabilities. Real-time signals can carry data, are queued (delivery to a specific thread is guaranteed), and can be prioritized.


START



Parent Child Processes


To be conformant with the POSIX.1 standard, processes must be kept separate, and this is achieved through the use of memory protection and name spaces.

POSIX assumes that each process in a system resides in a different name space and has its own symbols tables. The Memory Management Unit (MMU) is used to physically isolate processes from each another so that they cannot trample on each other's memory.



mmu

MMU and POSIX1



Also commonly referred to as "multi-processing," a process as defined by POSIX.1 will have its own name space. Two symbols defined globally will not conflict if they are located in two different processes, since they are in two different links. Three processes mapped by the MMU into separate physical memory pages. Each process is virtually isolated from other processes and it is therefore impossible for one process to write over another process' address space (unless the programmer intentionally performs address mappings). This diagram shows three processes mapped by the MMU into separate physical memory pages. Each process is virtually isolated from other processes and it is therefore impossible (unless programmer intentionally perrtforms address mappings) for one process to write over another process' address space.



START



6. Wichtige RT-OS-Firmen und RT-OSs

Wie aus den einleitenden Sätzen schon sichtbar wurde, werden durch die heutigen Forderungen bzgl. Zertifizierbarkeit von Zuverlässigkeit und Sicherheit für Realzeit-Systemen die Anforderungen an Firmen sehr hoch geschraubt, die sich an diesem Wettbewerb beteiligen wollen. Einige der grössten und bekanntesten sind hier angeführt. Wie man sieht, kommt in dieser Liste keine deutsche Firma vor. Bedenkt man, welch zentrale strategische Bedeutung RT-Systemen schon heute zukommen, dann kann dieses Faktum --aus deutscher Sicht-- zum Nachdenken anregen.

Wind River, gegründet in 1981, bekanntgeworden mit dem RT-System VxWorks; heute grosses Spektrum, z.B. Tornado@II, Platform NE

LynuxWorks, gegründet ca. 1988, RT-System LynxOS (RT-OS), BlueCat® (embedded)

FSMLabs, Entwicklung 1995-97 von RTLinux

RTAI, eigentlich keine firma, sondern ein Fachbereich der Universität von Mailand; erste Ideen vor 1998, ernsthafte Arbeit dann aber erst ab 1998 als der Linux Kernel 2.1.x.x. gestalt annahm.

SYSGO AG, gegründet 1991; kein eigenes betriebssystem, aber Serviceanbieter auf hohem Niveau mit Entwicklungsumgebung ELinOS, Vertrieb von LynxOS in Deutschland


START



7. Ein RT-OS am Beispiel von RTAI

Das folgende konkrete Beispiel eines Realzeitsystems benutzt das System RTAI (:= Real Time Application Interface) der Universität von Mailand in Verbindung mit Linux. Für eine erste Dokumentation zu RTAI siehe hier. Ds Beispiel wurde mit dem Entwicklungssystem ELinOS der Firma Sysgo erstellt.


Programm rt_process.c



// rt_process.c

#include <asm/system.h>
#include <linux/types.h>
#include <linux/module.h>
#include <linux/init.h>
#include <asm/io.h>
#include <rtai.h>
#include <rtai_sched.h>
#include <rtai_fifos.h>


/* timer period length in ns  */
#define TICK_PERIOD   10000000
/* 0 is highest priority, RT_LOWEST_PRIORITY is lowest */
#define TASK_PRIORITY 1
#define USES_FPU      0
#define STACK_SIZE    16384

/* number of fifo device (/dev/rtfX) */
#define FIFO          0
/* size of fifo in bytes */
#define FIFO_SIZE     16384


static RT_TASK rt_task0;


/* the realtime task */
static void sin_gen0(int notused)
{
    unsigned long now, last, nanoseconds;

    nanoseconds = 0;
    last = rt_get_cpu_time_ns();

    while (1)
    {
	now = rt_get_cpu_time_ns();
	nanoseconds = nanoseconds + now - last;
	while (nanoseconds >= 1000000000)
		nanoseconds -= 1000000000;
	last = now;

	/* put current nanoseconds into fifo */
	rtf_put(FIFO, &nanoseconds, sizeof(nanoseconds));

        /* suspend task util next period */
        rt_task_wait_period();
    }
}



/* called when module is inserted */
static int __init init_rt_task0(void)
{
    RTIME tick_period;

#if !defined(CONFIG_PPC)
    /* set periodic mode for timer */
    rt_set_periodic_mode();
#else
    /* on PowerPC we use oneshot mode to reduce system load */
    rt_set_oneshot_mode();
#endif
    /* initializing the task */
    rt_task_init(&rt_task0, sin_gen0, 0, STACK_SIZE, TASK_PRIORITY, USES_FPU, 0);
    /* creating fifo */
    rtf_create(FIFO, FIFO_SIZE);
    /* start timer */
    tick_period = start_rt_timer(nano2count(TICK_PERIOD));
    /* the realtime process should be choosen by the scheduler periodically */
    rt_task_make_periodic(&rt_task0, rt_get_time() + tick_period, tick_period);
    return 0;
}



/* called when module is removed */
static void __exit cleanup_rt_task0(void)
{
    /* kill timer */
    stop_rt_timer();
    /* kill fifo */ 
    rtf_destroy(FIFO);
    /* kill task */
    rt_task_delete(&rt_task0);

    return;
}

module_init(init_rt_task0);
module_exit(cleanup_rt_task0);


Programm scope.c



// scope.c

#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <string.h>
#include <sched.h>
#include <signal.h>

#ifdef X11
/* using "libforms" */
#include <forms.h>

/* scaling factor for the fixed window size */
#define WIN_SIZE 15
#define CANCEL ((obj != exitbut) && (!canceled))

FL_FORM *form;
FL_OBJECT *chartobj, *sinobj, *exitbut, *stepobj;


void create_form_form(void)
{
  FL_OBJECT *obj;


  form = fl_bgn_form(FL_NO_BOX,43*WIN_SIZE,23*WIN_SIZE);
  obj = fl_add_box(FL_BORDER_BOX,0,0,43*WIN_SIZE,32*WIN_SIZE,"");
  chartobj = obj = fl_add_chart(FL_LINE_CHART,2*WIN_SIZE,7*WIN_SIZE,39*WIN_SIZE,14*WIN_SIZE,"");
  fl_set_object_dblbuffer(obj,1);

  /* create exit button */
  exitbut = obj = fl_add_button(FL_NORMAL_BUTTON,15*WIN_SIZE,2*WIN_SIZE,14*WIN_SIZE,3*WIN_SIZE,"Exit");
    fl_set_object_boxtype(obj,FL_BORDER_BOX);
   fl_end_form();
}
#else
#define CANCEL (!canceled)
#endif

int canceled=0;

double sinus(double x);

void sigint_handler(int i)
{
  printf("Caught signal %i\n",i);
  canceled=1;
}

int main(int argc, char *argv[])
{
   int i;
#ifdef X11
   FL_OBJECT *obj;
#else
   int v;
#endif
   struct sched_param p;
   int fifo;
   long time_value;
   float sin_value;
   char *filename;

   signal(SIGINT, sigint_handler);
   signal(SIGTERM, sigint_handler);

   p.sched_priority=5;
   if ((i=sched_setscheduler(0, SCHED_FIFO, &p))) {
     perror("SetScheduler failed");
     return 1;
   }

   /* open FIFO for reading */
   if ((argc > 1) && (argv[1][0] != '-')) {
     filename = argv[1];
     fifo=open(filename, O_RDONLY);
   } else {
     /* try to open /dev/rtf0, then /dev/rtf/0 in case devfs in configured */
     filename = "/dev/rtf0 or /dev/rtf/0";
     if((fifo=open("/dev/rtf0", O_RDONLY)) == -1)
       fifo=open("/dev/rtf/0", O_RDONLY);
   }

   if (fifo == -1)
     {
       fprintf(stderr,"\nunable to open device %s (%s)\n\n",filename,strerror(errno));
       exit(1);
     }

#ifdef X11
   /* initializing scope window */
   fl_flip_yorigin();
   fl_initialize(&argc, argv, "Scope", 0, 0);
   create_form_form();
   fl_set_chart_bounds(chartobj,-1.5,1.5);
   fl_set_chart_maxnumb(chartobj,80);
   fl_set_chart_autosize(chartobj,0);
   fl_show_form(form,FL_PLACE_CENTER,FL_FULLBORDER,"Scope");
#endif

    do
    {
      /* reading time values from fifo */
     read(fifo, &time_value, sizeof(time_value));
     /* calculate sinus */
     sin_value = sinus(2*M_PI*1*time_value/1E9);
#ifdef X11
      /* insert value into diagramm */
     fl_insert_chart_value(chartobj,1,sin_value,"",1);
      /* update diagramm */
     obj = fl_check_forms();
#else
     v=(int)(sin_value*5.0)+5;
     for (i=0;i<v;i++) printf(" ");
     printf("*\n");
#endif
    }
    /* exit button pressed ? */
    while (CANCEL);
#ifdef X11
    fl_finish();
#endif
    close(fifo);
    return(0);
}


Programm sin.c



// sin.c

#include <stdio.h>
#include <stdlib.h>

#ifndef M_PI
#  define M_PI           3.14159265358979323846  /* pi */
#endif
#ifndef M_PI_2
#  define M_PI_2         1.57079632679489661923  /* pi/2 */
#endif

double sinus (double x)
{
  double acc = x;
  double sum = 0;
  int j;
  /* factorial of first N numbers */
  static double const fac[] = { 1.0, 6.0, 120.0, 5040.0, 362880.0 };
  double mult = 1.0;
  static double const pi2 = 2.0 * M_PI;    /* 2pi */
  static double const pi32 = 3.0 * M_PI_2; /* 3/2 pi */

  /* get x into [0, 2pi[ */
  while (x >= pi2) x -= pi2;

  /* get x into the first quadrant */
  if (x > pi32) {
    x = 2 * M_PI - x;
    mult = -1.0;
  } else if (x > M_PI) {
    x = x - M_PI;
    mult = -1.0;
  } else if (x > M_PI_2) {
    x = M_PI - x;
  }


  /* initialize for taylor series */
  sum = 0;  /* partial sum of taylor series */
  acc = x;  /* x^(2k + 1) */
  

  /* now the first components of taylor series */
  for (j = 0; j < 5; j++) {
    sum += acc / fac[j];
    acc *= x * x * (-1.0);
  }

  return mult * sum;

}


START



Testfragen


...to be done...


START