如何在C++中实现两个周期进程在Linux下?

发布于 2024-09-10 19:25:04 字数 159 浏览 4 评论 0原文

我正在 Linux 下用 C++ 进行实时编程。

我有两个进程,A 和 B。进程定期启动,每 5 毫秒一次。 B进程每10ms启动一次。进程A正在对数据进行一些更改。进程 B 正在读取该数据并显示它。

我对如何定期运行进程感到困惑,每个进程是否应该有两个 .cpp 程序?

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, and should I have two .cpp programs for each process?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

红衣飘飘貌似仙 2024-09-17 19:25:09

作为一种不同的解决方案,要创建两个相互通信的独立进程,您真正需要担心的是 IPC,而不是这些进程是如何创建的;即只需创建两个进程 A 和 B,就像您通常所做的那样(system()fork()popen() 等)。

现在,让它们相互交谈的最简单方法是使用 Named < a href="http://tldp.org/LDP/lpg/node15.html" rel="nofollow noreferrer">管道。它们是一种方式,因此您必须为 A -> 创建一种方式。 B 和另一个 B ->答:它们不需要任何锁定或同步,因为这是由内核/libc 自己完成的。一旦您设置了管道,您就可以像使用简单的网络连接/套接字一样使用它们。

如果您需要“更多动力(TM) (C)2010”,那么您必须使用共享内存信号量,或消息队列。然而,它们要复杂得多,所以我建议您首先研究一下命名管道。

现在,对于周期性运行,最好的方法是在每个程序的主函数中使用usleep(T);其中你使用的时间T可以从你上次跑步的时间开始计算,而不是在那里放一个固定的时间,这样你保证跑步花费的时间比预期的要长,你会睡更少的时间,以保证每X程序运行的毫秒数。

另一种方法是使用 SIGALRM ,如下所示:

#include <iostream>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <signal.h>

#include <pthread.h>
#include <semaphore.h>

static sem_t __semAlaram;

static void* waitForAlaram(void*)
{
    while( true )
    {
        sem_wait( &__semAlaram );
        std::cout << "Got alaram" << std::endl;
    }
    return NULL;
}


typedef void (*sighandler_t)(int);
static sighandler_t __handler = NULL;
static int count = 0;

static void sighandler(int signal)
{
    if ( signal == SIGALRM )
    {
        count++;
        sem_post( &__semAlaram );
        alarm(3);
    }
    else if ( __handler )
        __handler( signal );
}

int main(int argc, char **argv)
{
    if ( sem_init( &__semAlaram, 0, 0 ) != 0 )
    {
        std::cerr << strerror( errno ) << std::endl;
        return -1;
    }

    pthread_t thread;
    if ( pthread_create( &thread, NULL, waitForAlaram, NULL ) != 0 )
    {
        std::cerr << strerror( errno ) << std::endl;
        return -1;
    }

    __handler = signal( SIGALRM, sighandler );
    alarm(3);

    while( count < 5 )
    {
        sleep(1);
    }
    return 0;
}

您实际上并不需要其中的线程,但如果您的程序有不止一件事情,这可能是一个好主意,这样一个任务就不会影响计时的关键之一。无论如何,由于我已经以这种方式设置了该示例,因此按原样复制粘贴它会更容易。 ;-)

编辑:
现在我读了我的文章,我注意到一个致命的缺陷:SIGALRM 只能处理 1s 精度,而你需要 ms 精度。在这种情况下,如果您选择此解决方案,则必须使用 timer_create();它与 alarm()非常相似,但可以处理 ms 精度。在 Linux 中,man 2 timer_create 将为您提供如何使用它的示例。

As a different solution, to create two separate processes that communicate with each other, all you really have to worry about is the IPC, not really how these processes are created; i.e. just create the two processes, A and B, as you would normally do (system() or fork() or popen() etc).

Now, the easiest way to make them talk to each other is using Named Pipes. They are one way, so you'll have to create one for A -> B and another for B -> A. They don't need any locking or synchronization since that is kinda done by the kernel/libc themselves. One you set up the pipes, you could use them as though they were simple network connections/sockets.

If you need 'MORE POWER(TM) (C)2010', then you'll have to use Shared Memory and Sempahores, or Message queues. They are, however, much more complicated, so I suggest you look into named pipes first.

Now, for the periodical running, the best way is to use usleep(T) in each program's main function; where the time T you use can be calculated from the last time you ran, instead of putting a fixed time in there, so that you guarantee that is a run took longer than expected, you'll sleep less time, to guarantee that every X milliseconds your program runs.

Another way of doing it, is using SIGALRM like this:

#include <iostream>
#include <string.h>
#include <errno.h>

#include <unistd.h>
#include <signal.h>

#include <pthread.h>
#include <semaphore.h>

static sem_t __semAlaram;

static void* waitForAlaram(void*)
{
    while( true )
    {
        sem_wait( &__semAlaram );
        std::cout << "Got alaram" << std::endl;
    }
    return NULL;
}


typedef void (*sighandler_t)(int);
static sighandler_t __handler = NULL;
static int count = 0;

static void sighandler(int signal)
{
    if ( signal == SIGALRM )
    {
        count++;
        sem_post( &__semAlaram );
        alarm(3);
    }
    else if ( __handler )
        __handler( signal );
}

int main(int argc, char **argv)
{
    if ( sem_init( &__semAlaram, 0, 0 ) != 0 )
    {
        std::cerr << strerror( errno ) << std::endl;
        return -1;
    }

    pthread_t thread;
    if ( pthread_create( &thread, NULL, waitForAlaram, NULL ) != 0 )
    {
        std::cerr << strerror( errno ) << std::endl;
        return -1;
    }

    __handler = signal( SIGALRM, sighandler );
    alarm(3);

    while( count < 5 )
    {
        sleep(1);
    }
    return 0;
}

You don't really need the thread in there, but it might be a good idea if you have more than 1 thing your program does, so that one task will not affect the timing of the critical one. Anyway, since I already had that example set up that way, it was easier to just copy-paste it the way it was. ;-)

Edit:
Now that I read my post, I noticed a fatal flaw: the SIGALRM can only handle 1s precision, and you need ms precision. In that case, if you choose this solution, you'll have to use timer_create(); which is very similar to alarm(), but can handle ms precision. In linux, a man 2 timer_create will give you an example on how to use it.

記柔刀 2024-09-17 19:25:08

我认为,如果可能的话,创建一个具有两个线程的单个进程也可能是一个很好的解决方案,因为它们可能更容易共享资源并同步数据。

但是,如果您需要的不止于此,那么我认为您在陈述问题时需要更清楚。

I think that, if possible, create a single process with two threads might be a good solution also, since it might be much easier for them to share resources and synchronize their data.

But, if you need more than this, then I think you need to be clearer when stating your problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文