如何解决使用命名管道更好的方法
我已经有 3 个程序了,
它获取传感器数据并通过 TLS 将其发送到我的远程服务器。
我想减少 TLS 标头,
所以我决定把上面的程序分开来
3 * (传感器数据获取程序) + 1 * (tls 只发送程序),
使用命名 PIPE 作为进程间通信(不是套接字)。
但是现在我想知道哪个更好
-
使用 1 个命名管道和 3 个写入器 + 1 个读取器
#!/bin/sh mkfifo /tmp/tls/pipe /app/sensor1 & >> /tmp/tls/pipe /app/sensor2 & >> /tmp/tls/pipe /app/sensor3 & >> /tmp/tls/pipe /app/tls_sender /tmp/tls/pipe
-
使用每个写入器的 3 个命名管道 + 在读取器中使用 IO 多路复用(如
select()
)?#!/bin/sh mkfifo /tmp/tls/pipe1 mkfifo /tmp/tls/pipe2 mkfifo /tmp/tls/pipe3 /app/sensor1 & >> /tmp/tls/pipe1 /app/sensor2 & >> /tmp/tls/pipe2 /app/sensor3 & >> /tmp/tls/pipe3 /app/tls_sender /tmp/tls/pipe1 /tmp/tls/pipe2 /tmp/tls/pipe3
像 tls 发件人
#define SENSOR_NUM 3
int tls_flags[SENSOR_NUM];
char huge_buffer[HUGE_NUM];
int tls_send(int idx,char* buf) {
// set flags for each readfds index
// if all index counts to some threshold,send huge_buffer at once
}
int main(int argc,char *argv[]) {
...
int fd[SENSOR_NUM];
int state;
char buf[255];
fd_set readfds;
FD_ZERO(&readfds);
for(int i=0; i<SENSOR_NUM; i++)
{
fd[i] = open(argv[i+1],O_RDONLY);
FD_SET(fd[i],&readfds);
}
while(1) {
state = select(fd[2]+1,&readfs,NULL,NULL);
switch(state)
{
// case -1: error exception
// case 0 : no send
default:
for (int i=0; i<SENSOR_NUM; i++){
if (FD_ISSET(fd[i],&readfds))
read(fd[i],buf,255);
tls_send(i,buf);
}
break;
}
}
...
}
我猜前者更容易实现,速度更快,但后者会更稳定,但我不确定。
不使用信号量之类的,前者是否足够稳定?
还是后者更快或更容易受到攻击?
或者甚至没有 PIPE 的共享内存方法就足够了?
哪个更好,值得推荐?
谢谢。
解决方法
管道上的最大消息大小保证是原子的,因此不会交错消息:PIPE_BUF
。如果您的消息会更大,您将需要信号量或第一种方法的某种同步。 POSIX 保证它至少为 512 字节。在 Linux 上,它是 4096。请参阅 man (7) pipe
在性能方面,我认为差异可以忽略不计。如果您在很短的时间跨度内有很多小的写入,您可能会看到第一种方法的性能更好一些。这是因为您只需要一个用户空间/内核空间开关:在 read
上。而对于第二个,您将需要 select
和 read
。但是,在大多数情况下,我认为大部分时间都花在等待数据或复制数据上。等待 read
或 select
并不重要。
使用共享内存,您需要处理同步问题。这可能更快,但很复杂且容易出错。如果您遇到严重的性能问题,可以重新考虑这一点。
简而言之,我会推荐第一种方法。扩展或重用也更容易。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。