我已经在 Windows 上完成了大量编程,但现在我必须编写我的第一个 Linux 应用程序。

我需要使用 UDP 与硬件设备通信。我必须每秒发送 60 个大小为 40 字节的数据包。如果我在 1 秒内发送的数据包少于 60 个,就会发生不好的事情。数据包的数据可能需要一段时间才能生成。但是,如果数据尚未准备好通过网络发送,则可以发送上次发送的相同数据。计算机仅采用命令行设置,并且仅运行此程序。

我对 Linux 不太了解,所以我希望大致了解如何设置应用程序来满足这些要求。我希望得到这样的答案:

创建2个线程,一个用于发送数据包,另一个用于计算。

但我不确定事情是否那么简单(也许是这样)。也许制作某种守护进程从共享内存或其他东西发送数据包然后让另一个应用程序进行计算会更可靠?如果是多进程解决方案,您会推荐什么通信机制?有什么方法可以让我的应用程序比正常或类似的优先级更高吗?

附:越防弹越好!

有帮助吗?

解决方案

我张贴了这个答案来说明一个完全不同的方法来“明显”的一个,希望有人发现它是正是他们所需要的。我没想到它被选为最佳答案!对待谨慎使用此解决方案,因为有潜在的危险和并发的问题...

可以使用 setitimer()系统调用具有SIGALRM(报警信号)的毫秒指定次数后发送到你的程序。信号是中断正在执行的程序,让信号处理程序运行异步事件(有点像的消息)。

一组默认的信号处理程序由操作系统安装程序开始的时候,但你可以使用安装自定义信号处理程序的的sigaction()

因此,所有你需要的是一个单独的线程;使用全局变量,使得信号处理程序可以访问必要的信息,并发送断开新分组或重复最后分组作为合适的。

下面是为了你的利益的例子:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
int ticker = 0;

void timerTick(int dummy)
{
    printf("The value of ticker is: %d\n", ticker);
}

int main()
{
    int i;

    struct sigaction action;
    struct itimerval time;

    //Here is where we specify the SIGALRM handler
    action.sa_handler = &timerTick;
    sigemptyset(&action.sa_mask);
    action.sa_flags = 0;

    //Register the handler for SIGALRM
    sigaction(SIGALRM, &action, NULL);

    time.it_interval.tv_sec = 1;       //Timing interval in seconds
    time.it_interval.tv_usec = 000000; //and microseconds
    time.it_value.tv_sec = 0;  //Initial timer value in seconds
    time.it_value.tv_usec = 1; //and microseconds

    //Set off the timer
    setitimer(ITIMER_REAL, &time, NULL);

    //Be busy
    while(1)
        for(ticker = 0; ticker < 1000; ticker++)
            for(i = 0; i < 60000000; i++)
                ;
}

其他提示

我做了一个类似的项目:一个嵌入式Linux计算机上的一个简单的软件,以常规速度发出CAN消息

我会去两个线程的方法。给发送线程稍微更高的优先级,并使其再次发送相同的数据块,如果其他线程是在计算的那些块慢。

每秒60个UDP数据包是在大多数系统(包括嵌入的)相当宽松的,所以我不会花太多的汗水于优化螺纹之间的数据的共享和数据包的发送。

其实,我想说:保持它的简单!我你真的是在系统中唯一的应用程序,你必须在该系统合理控制,你什么都没有从复杂的IPC机制和其他技巧来获得。保持简单将帮助你产生更好的代码有缺陷少,在更短的时间,这实际上意味着测试更多的时间。

为你推荐会工作两个线程。如果你有他们之间的管道(),那么你的计算线程可以提供数据包,因为它们产生的,而你的通讯科线程使用select(),看看是否有任何新的数据。如果没有,那么它只是将来自它的最后一个的缓存。

我可能比简单的问题有点...

要使用一对线的建议听起来像它会做的伎俩,只要执行计算的负担不会太大。

除了使用pipe()通过Cogsy所建议的,我会倾向于使用一个互斥锁定的您使用来包含计算线程的输出存储器块 - 用它作为线程之间的转印区域

当你的计算线程准备输出到它会抓住该互斥的缓冲,写入到传送缓冲器,并释放互斥。

当您发送线程准备发送一个数据包,将“尽量”锁定互斥。 如果它获得锁,采取转移缓冲区的副本,并将其发送。 如果没有获得锁,发送最后一个副本。

您可以通过使用“好”,并指定一个负向调整数字给它更高的优先级控制你的进程的优先级。请注意,将需要这样做以超级用户(无论是作为根,或使用“须藤”),以便能够指定负值。


编辑:忘了补充 - 是在Linux pthreads的一个很好的教程。还描述了使用互斥的。

我不明白有多难你60包/秒的要求。是否每秒60个分组的突发填写要求?或者是每个数据包之间的尖锐的1/60秒的时间间隔需要?

这可能会去有点出入的话题,但另一个重要的问题是如何配置的Linux机器。我将自己使用的实时的Linux内核并禁用所有不需要的服务。其他明智的,有您的应用程序在某些时候错过了一个包,不管你选择什么样的架构的实际风险。

任何方式,两个线程应该很好地工作。

两个线程会的工作,你需要确保你通过这样的发送线程不会看到它通过一个更新中途锁定您的共享数据结构。

60每秒听起来不太复杂。

如果你真的关心调度,发送线程的调度策略设置为SCHED_FIFO和mlockall用于()的内存。这样一来,没有什么可以阻止它发送一个数据包(他们仍然可以走出去晚但如果其他的事情正在线路上同时发送)

必须有一些设备的宽容 - 每秒是罚款60包,但什么是设备的宽容?每秒20次?如果,如果它没有收到一个设备将失败,我会以三倍的速度向他们发送它要求。

我会从线程和使用的过程和(或许)信号和文件望而却步。既然你说“不好的东西”,如果你不送可能发生,你需要避免锁定UPS和比赛条件。和更易于与保存到文件分离过程和数据做。

沿着一个进程保存的数据的线到一个文件,然后东西重命名和重新开始。和其他过程拾取当前文件并每秒一次发送它的内容。

Windows不同,您可以复制(移动)在文件,而它是开放的。

遵循长期的 Unix 最佳实践:保持简单和模块化,解耦操作,让操作系统为您做尽可能多的工作。

这里的许多答案都是正确的,但我认为它们可以更简单:

  • 使用两个单独的进程,一个用于创建数据并将其写入标准输出,另一个用于从标准输入读取数据并将其发送。让基本I/O库处理进程之间的数据流缓冲,并让操作系统处理线程管理。

  • 首先使用计时器循环和虚假数据缓冲区构建基本发送器,并使其以正确的频率发送到设备。

  • 接下来让发送者从标准输入读取数据 - 您可以重定向文件中的数据,例如“发件人<文本数据”

  • 接下来构建数据生产者并将其输出通过管道传输到发送者,例如“生产者|发送者”。

现在,您可以根据需要创建新的生产者,而不会干扰发送方。该答案假设单向通信。

保持答案尽可能简单将使您取得更大的成功,特别是如果您还不太熟悉基于 Linux/Unix 的系统。这是学习新系统的绝佳机会,但不要过度。当工具可用时,很容易跳到复杂的答案,但当一个简单的抹子就足够了时,为什么还要使用推土机呢?互斥体、信号量、共享内存等都是有用且可用的,但增加了您可能并不真正需要的复杂性。

我同意这两个线程的方法。我也有两个静态缓存和共享的枚举。发送线程应该有这样的逻辑。

loop
    wait for timer
    grab mutex
    check enum {0, 1}
    send buffer 0 or 1 based on enum
    release mutex
end loop

另一个线程将具有这样的逻辑:

loop
    check enum
    choose buffer 1 or 0 based on enum (opposite of other thread)
    generate data
    grab mutex
    flip enum
    release mutex
end loop

此方式发送者总是具有用于它正在发送数据的整个时间的有效缓冲器。只有发电机线程可以改变缓冲区指针,它只能这样做,如果发送不在进行中。此外,该枚举倒装决不应如此多的周期以延迟优先级较高的发送者线程很长时间。

谢谢大家,我会用大家的意见。我希望我能比1选择更多的答案!

有关那些好奇。我没有源的设备,它的一个propietary锁定系统。我还没有做足够的测试,看看第二个是60包如何挑剔呢。那是他们所有的有限的文档说是“60包一秒钟。”由于尽管设备的性质,分组的突发将会是一件坏事。我想我将能够发送超过60秒,以弥补偶尔错过了包就完事了..

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top