Linux:操作系统对无特权的进程间总线的支持 [英] Linux: OS support for an unprivileged interprocess bus

查看:102
本文介绍了Linux:操作系统对无特权的进程间总线的支持的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试找到一种简单的解决方案,以在Linux主机上运行的非特权进程之间进行高性能的广播/多播通信.我正在寻找一种解决方案,该解决方案包括:1)简单,2)无特权(无root),3)与语言无关,4)面向数据包和5)高效(Gbit/s及以上).

为了说明这一点,我现有的代码仅使用UDP套接字进行单播通信,这完全符合上述要求(单播除外).我已经考虑通过让多个程序侦听同一UDP端口(使用SO_REUSEADDR和/或SO_REUSEPORT)来将其扩展为多播,但这实际上并没有将数据包的副本分发给所有进程.

我还研究了使用回送广播(127.255.255.255)来达到多个侦听过程,但是似乎我需要绑定到回送设备上的多个IP地址才能使其工作,并添加它们地址需要root.

解决方案

通过对Pete的建议进行扩展,我发现以下解决方案并不复杂.

以下Python 2程序通过多播/环回实现了一个简单的聊天程序.在Linux 3.13/Ubuntu 14.04上进行了测试.

 import os, socket, sys

# Use an administratively scoped multicast IP (RFC 2365).
mcast_group = '239.0.0.0'
port = 1234

# Communicate over the loopback interface.
ifc = '127.0.0.1'

def send(data):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)

    # Send over loopback interface.
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF,
        socket.inet_aton(ifc))

    sock.sendto(data, (mcast_group, port))

def listen():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)

    # Join group.
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
        socket.inet_aton(mcast_group) + socket.inet_aton(ifc))

    # Allow multiple subscribers.
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    sock.bind((mcast_group, port))
    while True:
        data, remote = sock.recvfrom(1024)
        print '#%d (%s:%d): %s' % ( (os.getpid(),) + remote + (data,) )


args = ' '.join(sys.argv[1:])
if args:
    send(args)
else:
    listen()
 

通过设置ifc = '0.0.0.0'并取消设置IP_MULTICAST_IF选项,可以轻松扩展到本地广播网段(LAN)上的通信.

接收自己的流量

唯一的问题是,似乎没有一种简单的方法来加入一个小组并发送给该小组中的其他所有人,同时也不会获得自己的访问量(即使使用相同的套接字进行监听)并发送).

IPPROTO_IP套接字选项IP_MULTICAST_LOOP无效;使用环回接口时,它无效;当通过网络进行通信时,它会阻止其他本地客户端接收消息.

不过,我可以通过过滤源地址来解决此问题.

(作为附带说明,我刚刚意识到QEMU包括本地支持使用多播发送虚拟网络流量.面对上述问题, QEMU开发人员还讨论了基于源地址的过滤,尽管他们似乎从未真正对它做任何事情,结果,QEMU VM收到了自己的传出流量的副本,尽管该流量通常在网络堆栈中被拒绝. )

I'm trying to find a simple solution for high-performance broadcast/multicast communication between unprivileged processes running on a Linux host. I'm looking for a solution that is 1) simple, 2) unprivileged (no root), 3) language-independent, 4) packet-oriented and 5) efficient (Gbit/s and up).

To put this in context, my existing code simply uses UDP sockets for unicast communication, which neatly matches the above requirements (except being unicast). I've looked into expanding this to multicast by having multiple programs listen to the same UDP port (using SO_REUSEADDR and/or SO_REUSEPORT), but this doesn't actually distribute copies of the packet to all the processes.

I've also looked into using loopback broadcast (127.255.255.255) to reach multiple listening processes, but it seems that I'll need to bind to multiple IP-addresses on the loopback device for this to work, and adding these addresses requires root.

解决方案

Expanding on Pete's suggestion, I've found the following solution, which is not too complex.

The following Python 2 program implements a simple chat program over multicast/loopback. Tested on Linux 3.13 / Ubuntu 14.04.

import os, socket, sys

# Use an administratively scoped multicast IP (RFC 2365).
mcast_group = '239.0.0.0'
port = 1234

# Communicate over the loopback interface.
ifc = '127.0.0.1'

def send(data):
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)

    # Send over loopback interface.
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_MULTICAST_IF,
        socket.inet_aton(ifc))

    sock.sendto(data, (mcast_group, port))

def listen():
    sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, 0)

    # Join group.
    sock.setsockopt(socket.IPPROTO_IP, socket.IP_ADD_MEMBERSHIP,
        socket.inet_aton(mcast_group) + socket.inet_aton(ifc))

    # Allow multiple subscribers.
    sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

    sock.bind((mcast_group, port))
    while True:
        data, remote = sock.recvfrom(1024)
        print '#%d (%s:%d): %s' % ( (os.getpid(),) + remote + (data,) )


args = ' '.join(sys.argv[1:])
if args:
    send(args)
else:
    listen()

This expands trivially to communication across the local broadcast segment (LAN) by setting ifc = '0.0.0.0' and unsetting the IP_MULTICAST_IF option.

Receiving one's own traffic

The only problem is that there appears to be no simple way to join a group and send to everyone else in the group without getting your own traffic as well (even by using the same socket for listening and sending).

The IPPROTO_IP socket option IP_MULTICAST_LOOP does not work; it has no effect when using the loopback interface, and when communicating over the network it prevents other local clients from receiving the messages.

I can work around this by filtering on the source address, though.

(As a side note, I just realized that QEMU includes native support for sending virtual network traffic using multicast. Faced with the above problem, the QEMU developers also discussed filtering based on source address, though it appears that they never actually did anything about it. As a result, the QEMU VM receives a copy of its own outgoing traffic, though the traffic is usually rejected in the network stack.)

这篇关于Linux:操作系统对无特权的进程间总线的支持的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆