LinuxQuestions.org
Download your favorite Linux distribution at LQ ISO.
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices

Reply
 
Search this Thread
Old 07-26-2010, 06:43 AM   #1
MarijaS
LQ Newbie
 
Registered: Jul 2010
Posts: 11

Rep: Reputation: 0
How to implement two periodical processes in C++ under Linux?


Hello,

I am doing real time programming in C++, under Linux.

I have two process, let me say A and B. A process is being started periodically, every 5ms. B process is being started every 10ms. The process A is doing some change of data. The process B is reading that data and displays it.

I am confused about how to run periodically processes.

Is the only way to create child process? Can I create independent processes on some other way?

Tnx!
 
Old 07-26-2010, 09:58 AM   #2
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,287

Rep: Reputation: 173Reputation: 173
look here first...

time.h

esp. look at timer_create

it's quite hard to follow. I have a messy example if you want.
I think it needs the pthread and realtime libraries.

LDFLAGS = -lrt -lpthread


if you are using an X toolkit they often have a timer.

Last edited by bigearsbilly; 07-26-2010 at 10:00 AM.
 
Old 07-26-2010, 04:56 PM   #3
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 453Reputation: 453Reputation: 453Reputation: 453Reputation: 453
Quote:
Originally Posted by MarijaS View Post
Hello,

I am doing real time programming in C++, under Linux.

I have two process, let me say A and B. A process is being started periodically, every 5ms. B process is being started every 10ms. The process A is doing some change of data. The process B is reading that data and displays it.

I am confused about how to run periodically processes.

Is the only way to create child process? Can I create independent processes on some other way?

Tnx!
Independent processes are child processes of the shell you invoke them from.

Do you really want processes or you want threads ? Regarding the latter look up "POSIX threads" -> https://computing.llnl.gov/tutorials/pthreads/ .

The info is in addition to bigearsbilly's post.
 
Old 07-27-2010, 06:04 AM   #4
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,287

Rep: Reputation: 173Reputation: 173
the timer_create functions generally run as non-joinable threads.
(though I believe it's not mandatory)

so mutexes, conditions etc, are available to manage data.
on my linux and freebsd anyway.


if you want a scruffy example of using them
let me know.
 
Old 07-27-2010, 11:34 AM   #5
MarijaS
LQ Newbie
 
Registered: Jul 2010
Posts: 11

Original Poster
Rep: Reputation: 0
Thank you for your suggestions!
I really need independent processes...

@bigearsbilly
Some example would be very useful!

Last edited by MarijaS; 07-27-2010 at 11:37 AM.
 
Old 07-27-2010, 12:06 PM   #6
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,522

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
Quote:
Originally Posted by MarijaS View Post
Thank you for your suggestions!
I really need independent processes...
Must you start and stop, and then restart your processes, every 10ms and 5ms, respectively? Or can they be run once and remain dormant (ie in a wait state) for the aforementioned periods while they are not processing data?

Starting and stopping processes is major CPU-hog; you would be better off placing the processes in a wait state, and perhaps even better off utilizing a multi-threaded solution.

Your requirements are too vague to provide further assistance. If you plan to stick with independent processes, I would suggest you look into using shared-memory for the data.
 
Old 07-27-2010, 03:10 PM   #7
zirias
Member
 
Registered: Jun 2010
Posts: 361

Rep: Reputation: 59
To get periodical tasks, I'd follow dwhitney67's suggestion and use alarm(2) at the beginning of each computation period and send the process to blocked state e.g. by calling wait().

But the instant the SIGALRM occurs, the scheduler could STILL decide to first run another process out of the ready queue, so this doesn't qualify as a true real time system. If you need true realtime, you'll need a different scheduler (for example an implementation of rate monotonic scheduling) in the kernel.
 
Old 07-28-2010, 03:17 AM   #8
MarijaS
LQ Newbie
 
Registered: Jul 2010
Posts: 11

Original Poster
Rep: Reputation: 0
I can run processes once, and then put them in blocked (wait) state.

Actually, the problem is that the period of process A should be as much as it is possible accurate (5ms). For the process B it isn't so important. So I don't know what is the best way to deal with precision. Is it complicated to implement some other scheduler? It seems to me complicated...

I have created independent processes, each in one .cpp file, and I am starting them from bash file. Is that OK? Then I can try to use shared memory for inter-process communication?
 
Old 07-28-2010, 03:19 AM   #9
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,287

Rep: Reputation: 173Reputation: 173
OK try this. It uses the POSIX realtime library.

It's a silly toy to write independent counters to the terminal.
it may mess up your cursor.


It's a very very very scruffy work in progress example in C++, so apologies.
the key code is is the set_timer function.
esp. the:
Code:
    se.sigev_notify = SIGEV_THREAD;
    se.sigev_value.sival_ptr = data;
    se.sigev_notify_function = timer_thread;  # the callback
    se.sigev_notify_attributes = NULL;
compile like this:
Code:
 
export LDLIBS='-lrt -lpthreads'  # link realtime and pthreads
make timers.cpp
Code:
/*
 * (c) bigearsbilly
 *
 *    need LDLIBS =  -lrt -lpthread
 */
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <iomanip>

pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;


struct blob {

    int row;
    int column;
    std::string buffer;
    size_t count;
    timer_t timer_id;

    blob(int r, int c, std::string s) :
		row(r), column(c), buffer(s), count(0) {};

    friend std::ostream& operator<< (std::ostream& out, blob & b) {

	out << '\033' << "[" << b.row << ";" << b.column <<
		"f" << b.buffer << b.count << std::flush;

	++b.count;
	return out;
    }

};

void timer_thread (union sigval si)
{

    blob* p = static_cast<blob *>(si.sival_ptr);

    if(si.sival_ptr) {
	pthread_mutex_lock(&mutex);
	std::cout << *p;
	pthread_mutex_unlock(&mutex);
    }
}

typedef void (t_callback) (union sigval si);

int set_timer(float delay, float interval, t_callback func, void * data) 
{
    int status =0;
    struct itimerspec ts;
    struct sigevent se;
    blob * b = static_cast<blob *>(data);

    se.sigev_notify = SIGEV_THREAD;
    se.sigev_value.sival_ptr = data;
    se.sigev_notify_function = timer_thread;
    se.sigev_notify_attributes = NULL;

    status = timer_create(CLOCK_REALTIME, &se, &(b->timer_id));

    ts.it_value.tv_sec = abs(delay);
    ts.it_value.tv_nsec = (delay-abs(delay)) * 1e09;
    ts.it_interval.tv_sec = abs(interval);
    ts.it_interval.tv_nsec = (interval-abs(interval)) * 1e09;

    status = timer_settime(b->timer_id, 0, &ts, 0);
    return 0;
}

int main(int argc, char ** argv)
{

    unsigned int timeout = 0;
    if(argc == 2) {
	timeout = atoi(argv[1]);
    }

    blob a(5,12,"seconds:");
    blob b(10,12,"tenths:");
    blob c(15,12,"hundredths:");
    blob d(20,12,"thousandths:");

    std::cout << '\033' << " L";
    std::cout << '\033' << "7";
    std::cout << '\033' << "[2J";
    std::cout << '\033' << "[?25l";

    set_timer(1, 1.0, timer_thread, &a );
    set_timer(1, 0.1, timer_thread, &b );
    set_timer(1, 0.01, timer_thread, &c );
    set_timer(1, 0.001, timer_thread, &d );

    getchar();
    std::cout << '\033' << "8";
    std::cout << '\033' << "[?25h";

    return 0;
}
p.s. you may find the thousands 'slip' as the timer overruns.

Last edited by bigearsbilly; 07-28-2010 at 03:23 AM.
 
Old 07-28-2010, 03:23 AM   #10
zirias
Member
 
Registered: Jun 2010
Posts: 361

Rep: Reputation: 59
You can just test the alarm()/wait() approach, it should be "somwhat accurate" as long as the system isn't under heavy load. Just be sure to set the alarm() as the FIRST thing you do on each computational period, so you don't accidently add your own execution time to the period.

As for implementing an own scheduler: This is probably a LOT of trouble and only worthwile if you REALLY need TRUE realtime -- and you'll still face some problems like "stolen" cycles in management mode. If it's an embedded system whose realtime requirements are crucial for ppls health, go for it
 
Old 07-28-2010, 06:34 AM   #11
MarijaS
LQ Newbie
 
Registered: Jul 2010
Posts: 11

Original Poster
Rep: Reputation: 0
Thank you!
For this time I'll skip TRUE realtime and try to deal with your suggestions.
 
Old 07-28-2010, 01:43 PM   #12
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,287

Rep: Reputation: 173Reputation: 173
the timer_create and timer_settime examples
I posted are part of the POSIX realtime library.

here is a much simpler but less fun example...
don't forget to link -lrt -lpthread
Code:
/*
 * (c) bigearsbilly
 *
 *    need LDLIBS =  -lrt -lpthread
 */
#include <pthread.h>
#include <signal.h>
#include <sys/time.h>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <iomanip>

using std::cout;
using std::cerr;
using std::endl;

typedef void (timer_callback) (union sigval);

int set_timer(timer_t * timer_id, float delay, float interval, timer_callback * func, void * data) 
{
    int status =0;
    struct itimerspec ts;
    struct sigevent se;

    se.sigev_notify = SIGEV_THREAD;
    se.sigev_value.sival_ptr = data;
    se.sigev_notify_function = func;
    se.sigev_notify_attributes = NULL;

    status = timer_create(CLOCK_REALTIME, &se, timer_id);

    ts.it_value.tv_sec = abs(delay);
    ts.it_value.tv_nsec = (delay-abs(delay)) * 1e09;
    ts.it_interval.tv_sec = abs(interval);
    ts.it_interval.tv_nsec = (interval-abs(interval)) * 1e09;

    status = timer_settime(*timer_id, 0, &ts, 0);
    return 0;
}

void callback(union sigval si)
{
    char * msg = (char *) si.sigval_ptr;
    std::cout << msg << std::endl;
}

int main(int argc, char ** argv)
{

    timer_t tick;
    timer_t tock;
    set_timer(&tick, 1, 1, callback, (void *) "tick" );
    set_timer(&tock, 1.5, 1, callback, (void *) "tock" );
    getchar();

    return 0;
}
but this is very simplistic, to get started.
you will need to read the documentation.

Last edited by bigearsbilly; 07-28-2010 at 01:45 PM.
 
1 members found this post helpful.
Old 07-29-2010, 06:46 AM   #13
MarijaS
LQ Newbie
 
Registered: Jul 2010
Posts: 11

Original Poster
Rep: Reputation: 0
Thank you!
Beacuse this is my first time working with timers of the POSIX, for the beginning I did something very similar to your code. I just used SIGEV_SIGNAL instead of SIGEV_THREAD.
Compaling was successful. But running not. I have some errors in object file: Undefined reference to 'timer_create' and Undefined reference to 'timer_settime'.
I really don't know what is the problem...
 
Old 07-29-2010, 07:17 AM   #14
dwhitney67
Senior Member
 
Registered: Jun 2006
Location: Maryland
Distribution: Kubuntu, Fedora, RHEL
Posts: 1,522

Rep: Reputation: 332Reputation: 332Reputation: 332Reputation: 332
You have to link your code the the real-time library; specifically, add -lrt to your GCC link statement. For example
Code:
gcc MyProg.c -lrt
 
Old 07-29-2010, 09:55 AM   #15
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: FreeBSD, Debian, Mint, Puppy
Posts: 3,287

Rep: Reputation: 173Reputation: 173
Yes It took me lots of searching to get an idea of how to use
it. There is scant documentation on line.


:-) Undefined reference to 'timer_create' and Undefined reference to 'timer_settime'.


You also need pthread - it may compile
without but probably will break.

easy way to link the libraries is like this:

(assuming prog.cpp)
Code:
export LDLIBS='-lrt -lpthread'
make prog
 
  


Reply

Tags
c++, linux


Thread Tools Search this Thread
Search this Thread:

Advanced Search

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
how to implement piping between different processes in Linux Xianli Linux - Newbie 2 05-16-2008 09:51 AM
how to implement piping between different processes in Linux?? Xianli Programming 2 05-15-2008 08:42 AM
Clone a 300Gb disk on a periodical base on Linux(Fedora5)?? byteclock Linux - Software 1 05-23-2006 02:11 AM
periodical performance collapse on centrino/mdk10.0 tac Linux - Laptop and Netbook 0 11-21-2004 08:02 AM


All times are GMT -5. The time now is 04:02 AM.

Main Menu
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration