Xorg multiseat

出自 ArchWiki

此条目或章节需要扩充。

原因: 展示如何为多个用户配置 PulseAudio 而无需系统范围运行 PulseAudio。 解释如何仅使用一张显卡(和/或 X Server)且无需 Xephyr 来实现 Multiseat。(在Talk:Xorg multiseat中讨论)

此条目或章节需要语言、wiki 语法或风格方面的改进。请参考 Help:Style

原因: 以第一人称撰写,更像一篇博客文章。(在Talk:Xorg multiseat中讨论)

Multiseat 是一种特定的设置,其中 N 个用户同时在一台计算机上工作。 这是通过拥有 N 个显示器、N 个键盘和 N 个鼠标来实现的。 优点非常明显

  • 更低的功耗(仅一台计算机)
  • 更少的硬件购买

要求

此条目或章节已过时。

原因: 本节引用了过时的硬件(PS/2 键盘、AGP 或 PCI GPU、10k RPM 硬盘等...),自 2007 年以来内容没有重大更新:这对于当前一代硬件仍然相关吗?(在Talk:Xorg multiseat中讨论)

键盘和鼠标

任何标准的 PS/2 或 USB 键盘都足够了。鼠标也是如此。

图形硬件

为了获得最佳效果,您将需要两张显卡。我使用了一张 nVidia FX5500 AGP 和一张 nVidia 6200 PCI。如果您稍微找找,您肯定可以找到价格合理的全新且不错的 PCI 显卡。

可以使用只有一个双头输出的显卡(就像大多数 nvidia 卡一样),但这有一些限制:您必须在第二个显示器上使用 Xephyr,从我读到的内容来看,这似乎是一个相当混乱的解决方案,并且为了获得最佳使用效果,两个屏幕需要相同的分辨率。

如果您有两个 pci-express 插槽,请充分利用它们!这样您甚至可以同时玩两个游戏。(PCI 太慢,无法舒适地玩游戏)

处理器和内存

如果您真的要在同一台计算机上与两个用户一起工作,我至少建议使用双核处理器和充足的 RAM。为了获得舒适的使用体验,还建议使用快速硬盘驱动器(10,000 RPM 或更高)。

软件

您将需要带有显卡驱动程序的 Xorg(根据一些来源,闭源 nvidia 驱动程序在这方面比开源 nvidia 驱动程序更好,我没有亲自测试过)和 evdev (xf86-input-evdev) 驱动程序。 就这些。 所有这些都可以在 Arch Linux core 和 extra 仓库中找到。

一些 X 知识

如果您知道 X 的工作原理,这将容易得多。 在开始之前,建议使用 xorg.conf(5) 生成一个适用于单屏幕的干净配置。 通读此 xorg 配置并熟悉它。 像往常一样,手册页将为您提供大部分答案。 您可以参考一些手册页:Xorg(1), Xserver(1), startx(1), xdm(8), xinit(1)

您还可以查看以下命令的输出以获得一些提示

# X -configure
# X -showopts

定义

为了使本文清晰易懂,我将使用以下定义

  • 屏幕 (screen):屏幕是 Xorg 可以显示内容的东西。 屏幕有一个显示器和一张显卡分配给它。
  • 显示器 (monitor):物理显示器,就像您现在坐在面前的那个。
  • 服务器布局 (server layout):定义要使用的屏幕、键盘和鼠标。
  • seat:一个工作场所,配备物理显示器、物理键盘和物理鼠标。

技巧和窍门

  • 在您的计算机上设置 ssh,以便您可以从另一台计算机(例如笔记本电脑)ssh 连接到该机器。 这非常有用,因为您可能会遇到 X 不再响应或根本不给您图像的情况。
  • 找出哪个键盘和鼠标是哪个:打开一个终端并使用 cat 来找出。 例如,cat /dev/input/mouse1。 如果您随后移动鼠标,并且看到所有奇怪的事情发生,那么这就是您正在移动的鼠标。 键盘也是如此,键盘被称为 eventN。
  • 首先尝试基本配置。 暂时不要开始使用花哨的东西,首先让一个非常基本的 Xorg 工作起来。
  • 创建所有相关配置文件的备份。 你是什么意思你要跳过这个?

关于 evdev

evdev 是一个 Xorg 驱动程序,它可以利用内核事件设备,您可以在 /dev/input 中找到它们。

将设备连接到 seat

systemd 的 loginctl(1) 允许您通过创建 udev 规则将设备分配给 seat。

识别设备

查看默认 seat (seat0) 的状态,这是一个示例

# loginctl seat-status seat0
seat0
        Sessions: *11
         Devices:
                  ├ /sys/devices/pci0000:00/0000:00:02.0/0000:03:00.0/drm/card0
                  │ (drm:card0)
                  ├ /sys/devices/pci0000:00/0000:00:02.0/0000:03:00.0/graphics/fb0
                  │ (graphics:fb0) "radeondrmfb"
                  ├ /sys/devices/pci0000:00/0000:00:02.0/0000:03:00.1/sound/card1
                  │ (sound:card1) "Generic"
                  │ └ /sys/devices/pci0000:00/0000:00:02.0/0000:03:00.1/sound/card1/input15
                  │   (input:input15) "HD-Audio Generic HDMI/DP,pcm=3"
                  ├ /sys/devices/pci0000:00/0000:00:12.0/usb3
                  │ (usb:usb3)
                  │ ├ /sys/devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.2/0003:046D:C52B.0006/input/input5
                  │ │ (input:input5) "Logitech Unifying Device. Wireless PID:101b"
                  │ └ /sys/devices/pci0000:00/0000:00:12.0/usb3/3-1/3-1:1.2/0003:046D:C52B.0006/input/input6
                  │   (input:input6) "Logitech Unifying Device. Wireless PID:200a"
                  ├ /sys/devices/pci0000:00/0000:00:14.2/sound/card0
                  │ (sound:card0) "SB"
                  │ ├ /sys/devices/pci0000:00/0000:00:14.2/sound/card0/input7
                  │ │ (input:input7) "HDA ATI SB Line"
                  │ └ /sys/devices/pci0000:00/0000:00:14.2/sound/card0/input9
                  │   (input:input9) "HDA ATI SB Rear Mic"
                  ├ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0/drm/card1
                  │ (drm:card1)
                  ├ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0/graphics/fb1
                  │ (graphics:fb1) "radeondrmfb"
                  ├ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.1/sound/card2
                  │ (sound:card2) "HDMI"
                  │ └ /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.1/sound/card2/input16
                  │   (input:input16) "HDA ATI HDMI HDMI/DP,pcm=3"
                  ├ /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.0/input/input2
                  │ (input:input2) "CHESEN PS2 to USB Converter"
                  ├ /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.1/input/input3
                  │ (input:input3) "CHESEN PS2 to USB Converter"
                  └ /sys/devices/pci0000:00/0000:00:12.1/usb4/4-2/4-2:1.0/input/input4
                    (input:input4) "Microsoft Microsoft 3-Button Mouse with IntelliEye(TM)"

如果您不确定,请尝试与 lspcilsusb 进行比较以识别设备。

分配设备

Seat 是基于显卡创建的。 因此,我们将从分配显卡开始

# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0/drm/card1
# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.0/graphics/fb1

然后添加输入设备。 第一个示例(不推荐)从上面的列表中按端口和子设备添加了三个 USB 设备

# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.0/input/input2
# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1/4-1:1.1/input/input3
# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:12.1/usb4/4-2/4-2:1.0/input/input4

这不太理想,因为用另一个键盘替换键盘只有在新键盘包含相同的子设备(1.01.1)时才有效,并且如果键盘和鼠标意外地交换到彼此的 USB 端口中,它们将不会分配给预期的 seat,并将最终回到默认的 seat0。 更灵活的方法是将特定的 USB 端口添加到 seat,允许插入该 USB 端口的任何设备分配给该 seat(键盘、鼠标、USB 声卡等)。 在这里,两个 USB 端口被分配给 seat,您可以看到它刚刚从上面的列表中删除末尾部分

# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:12.1/usb4/4-1
# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:12.1/usb4/4-2

使用多个声卡,您可以为每个 seat 分配一个声卡,这将开箱即用地与每个用户会话 pulseaudio 一起运行

# loginctl attach seat1 /sys/devices/pci0000:00/0000:00:04.0/0000:02:00.1/sound/card2

您应该能够看到硬件已划分为两个 seat

# loginctl seat-status seat0
# loginctl seat-status seat1

seat 名称只是字符串标签,因此您可以将 seat 称为您喜欢的任何名称 - seat-1seatleftseat-tv 都是有效的名称。 虽然您不必使用 seat 前缀,但这并不推荐,因为某些程序(例如 LightDM)仅将其默认选项应用于与表达式 seat* 匹配的 seat,因此任何不以单词 seat 开头的名称都可能需要额外的手动配置。 seat0 是默认的 seat 名称,无法更改。

任何未专门标记到 seat 的设备都将最终进入 seat0。 如果设备标记到给定的 seat,则所有子设备也属于该 seat。 这对于热插拔接口最有用,例如上述示例,该示例将 USB 端口分配给特定的 seat,以便插入这些端口的任何设备都将自动继承在 USB 端口本身上设置的 seat。

loginctl attach 创建和删除与 /etc/udev/rules.d/72-seat-*.rules 匹配的 udev 规则文件,因此如果您希望备份您的 seat 配置,这些是要保存和恢复的文件。

在标记为 master-of-seat 的设备出现之前,每个 seat 都不会显示为就绪。 默认的 udev 规则会自动将此标记应用于任何 drmgraphics 设备。 因此,如果您不将这些设备之一作为 seat 的一部分(例如,仅具有键盘和音频的视障用户),则需要手动编辑 loginctl 创建的 udev 规则,并在 seat 可用之前指定此标记。 查看默认的 udev 规则以获取示例。

设置 Xorg

由于您可以使用 loginctl 将设备连接到 seat,因此无需特定的 Xorg 配置,因此如果通过 loginctl 连接设备,则可以跳过创建 Xorg 配置文件。 另请注意,将 ServerFlags "AutoAdd*" 选项设置为 false 会强制 Xorg 忽略大多数 loginctl 连接。

如果您确实选择使用自定义 Xorg 配置(例如,您有一张 nVidia 卡并想要设置高级显示选项),那么该过程与通常情况大致相同,主要区别在于您为每个 seat 定义一个 ServerLayout 部分,并在每个服务器布局中包含 MatchSeat 语句以指示它应该应用于哪个 seat。 您还可以将 MatchSeat 指令应用于图形设备和显示器本身,以避免定义 ServerLayout,如果您不需要任何 ServerLayout 功能。 请注意,任何缺少 MatchSeat 指令的部分对于所有服务器布局和 seat 都是可见的,因此请确保配置的其他部分阻止多个 seat 尝试访问同一设备。 (一个常见的错误是允许两个 seat 访问相同的显示设备,这将导致一个 seat 工作而其他 seat 无法启动。)

以下是这种手动配置类型的示例。 您可以为两个服务器布局创建部分或整个配置集,每个服务器布局都分配有自己的键盘、鼠标、显卡和显示器。 如果您省略某个部分(例如 InputDevice 部分),则 Xorg 默认值将适用。

xorg.conf.d tree example:
├── 00-keyboard.conf   #created by localectl
├── 31-monitor-seat0.conf
├── 32-monitor-seat1.conf
├── 40-serverflags.conf
├── 41-graphic-seat0.conf
├── 42-graphic-seat1.conf
├── 51-screen-seat0.conf
├── 52-screen-seat1.conf
├── 61-layout-seat0.conf
└── 62-layout-seat1.conf

定义可用的输入设备

配置的这一部分告诉 Xorg 它有哪些可用的输入设备。 输入设备是键盘和鼠标,但也可能是触摸屏和笔等。

按照 Xorg#输入设备 中的说明配置您的设备。 “Identifier”将允许您分配给 ServerLayout,“Device”定义您正在配置的物理设备。

01-keyboard-seat0.conf
Section "InputDevice"
        Identifier      "keyboard0"
        Option          "Device"                "/dev/input/event1"
        #Option          "Device"                "/dev/input/by-path/pci-0000:00:1a.0-usb-0:1.6:1.0-event-kbd"  # or by path

        # GrabDevice no longer has any effect: https://www.spinics.net/lists/xorg/msg59881.html
        Option "GrabDevice" "on" # prevent send event to other X-servers
EndSection

其他 输入设备 也是如此。

显示器

按照 Xorg#显示器设置 中的说明配置您的显示器。 请密切注意标识符。

31-monitor-seat0.conf
Section "Monitor"
    Identifier             "monitor0"
EndSection

ServerFlags

40-serverflags.conf
Section "ServerFlags"
        Option "AutoAddGPU" "off"
EndSection

显卡

仔细查看 BusID。 此选项指定要使用的硬件卡。 您可以使用 lspci 找出 BusId。 但是,您很快就会发现这并不总是匹配。 这是因为 lspci 以十六进制形式显示设备地址。 但是,Xorg 使用十进制形式。 因此,您需要将地址从十六进制形式转换为十进制。 因此,lspci 中 0:0a:0 的设备地址在 xorg.conf 中将变为 0:10:0。

42-graphic-seat1.conf
Section "Device"
        Identifier      "graphic0"
        Driver          "nvidia"
        Option          "NoLogo"                "1"  # Remove nvidia branding at startup
        BusId           "PCI:1:0:0"
        MatchSeat       "seat-1"                     # Needed when only configuring part of Xorg for non-seat0.
        Option          "Monitor-DVI-1"         "monitor1"  #assigns monitor configuration to graphic output port
EndSection

另一个更高级的示例,其中使用了 nVidia TwinView,以便一个 seat 具有双显示器,其中一个显示器为横向,另一个为纵向

42-graphic-seat-nvidia.conf
Section "Device"
        Identifier "nvidia"
        Driver "nvidia"
        BusID "PCI:66:0:0"  # lspci reports this as 42:00.0, so 42 hex is 66 decimal

        # See the nVidia documentation for what these options do.  They of
        # course only apply if you have an nVidia card and you are using their
        # closed-source driver.
        Option "UseDisplayDevice" "DP-3"
        Option "MetaModes" "DP-3: 2560x1600, DP-0: 1600x1200 { Rotation=left }"
        Option "TwinViewOrientation" "LeftOf"

        # Not needed, avoid errors in logs
        Option "ConnectToAcpid" "false"

        # Do not automatically set the DPI based on screen size, use the traditional
        # value to avoid fonts becoming overly large.
        Option "UseEdidDpi" "False"
        Option "DPI" "96 x 96"

        # No MatchSeat option is needed here if it's given in the ServerLayout instead.
        #Option "MatchSeat" "seat-nvidia"
EndSection

屏幕

请密切注意“monitor”选项。

51-screen-seat0.conf
Section "Screen"
        Identifier              "screen0"
        Device                  "graphic0"
        Monitor                 "monitor0"
        DefaultDepth    24
        Subsection "Display"
                Depth   24
                Modes   "1280x1024"     "1024x768"
        EndSubsection
EndSection

ServerLayout

为您拥有的每个 seat 创建一个部分(注意标识符),其中包含各自的键盘、鼠标和屏幕。

62-layout-seat1.conf
Section "ServerLayout"
        # The Identifier is not really important but must be unique.
        Identifier      "seat-1"

        # This controls which Screen section is used in the layout, which in turn
        # dictates which GPU and monitor will be used.  The numbers can be omitted
        # if only one Screen is used (normally the case unless you are combining
        # monitors from different video cards).
        Screen          "screen1"       0                   0

        # InputDevice sections can usually be omitted
        InputDevice     "mouse1"        "CorePointer"
        InputDevice     "keyboard1"     "CoreKeyboard"

        Option          "SingleCard" "on"   # use this to simplfied isolatedevice option

        # MatchSeat means this layout will only be used when the "-seat seat-1"
        # parameter is given to /usr/bin/X, which most display managers will do
        # automatically.
        MatchSeat       "seat-1"
EndSection

其他提示

  • 确保在初始重启之前删除各自用户目录中的 ~/.Xauthority 文件。
  • 为了避免画面撕裂,这似乎对几乎所有配置都有帮助 - 将此添加到 /etc/environment
CLUTTER_PAINT=disable-clipped-redraws:disable-culling
CLUTTER_VBLANK=True

测试

在我们开始修改登录管理器之前,我们将首先开始测试各个 seat。 如果这些工作正常,那么我们就一切顺利了。

我使用了 twm(微型窗口管理器)来测试我的 seat 是否工作,但是您完全可以使用 KDE、gnome 或任何其他桌面环境或窗口管理器。 我在我的 ~/.xinitrc 中使用了这个

exec twm

使用以下命令测试单个 seat

startx -- -layout seat0 -config xorg.conf.multiseat

对您拥有的每个 seat 执行此操作。 如果它们都工作正常并且键盘/鼠标组合匹配,那么恭喜您! 您几乎完成了! 如果您想知道为什么我没有使用新配置文件的完整路径,那是因为当以非 root 身份运行时,X 不允许这样做。 它将在相对于 /etc/X11 的位置搜索 xorg.conf.multiseat。

设置登录管理器

此条目或章节需要扩充。

原因: 需要 SDDM 的说明。(在Talk:Xorg multiseat中讨论)

对于 XDM

打开 /etc/X11/xdm/Xservers 并设置以下变量(此示例演示了两个 seat)

# NOTE: do not add -sharevts on seat0, otherwise it may reset in about 10~20 minutes automatically.
:0 local /usr/bin/X :0 vt07 -nolisten tcp  -novtswitch -layout seat0 -seat seat0
:1 local /usr/bin/X :1 vt08 -nolisten tcp -novtswitch -layout seat-1 -seat seat-1
注意: 如果 XDM 未正确地将 seat 编号分配给会话(loginctl 将显示没有 seat 的会话),则您连接的设备可能会出现奇怪的行为,例如缺少权限、pulseaudio 未检测到声卡... LightDM 应该没问题。

如果您使用 Arch Linux 主题,请为每个屏幕编辑 /etc/X11/xdm/xdm-config

DisplayManager._0.setup:        /etc/X11/xdm/arch-xdm/Xsetup
DisplayManager._0.startup:      /etc/X11/xdm/arch-xdm/Xstartup
DisplayManager._0.reset:        /etc/X11/xdm/arch-xdm/Xreset
DisplayManager._1.setup:        /etc/X11/xdm/arch-xdm/Xsetup
DisplayManager._1.startup:      /etc/X11/xdm/arch-xdm/Xstartup
DisplayManager._1.reset:        /etc/X11/xdm/arch-xdm/Xreset

对于 LightDM

LightDM 具有自动 multiseat 检测功能(从 loginctl list-seats 提供的 seat 列表中拉取)。 如果您有手动 Xorg 配置文件并想使用它,请确保在其中指定有效的 MatchSeat 值(请参阅上文)。 这是因为 LightDM 会自动将 -seat seat0 或类似的参数传递给 /usr/bin/X,因此 Xorg 将忽略任何 MatchSeat 与当前 seat 不匹配的部分。 (因此,如果您忘记完全指定 MatchSeat,这些部分将应用于每个 seat,在显示设备的情况下,这意味着一个或多个 seat 很可能根本无法启动,因为它们都在争夺相同的显示器。)

如果需要,您可以在 /etc/lightdm/lightdm.conf 上进行配置

[LightDM]
run-directory=/run/lightdm

[Seat:*]
greeter-session=lightdm-gtk-greeter
greeter-hide-users=false # Bug: lightdm-gtk-greeter does not load user saved session when greeter-hide-users=true[1]
session-wrapper=/etc/lightdm/Xsession

[Seat:seat0]
xserver-command=/usr/bin/X :0
# If you cannot put `MatchSeat "seat0"` in the `ServerLayout` section for some reason, you can force a layout here.
xserver-layout=seat0

[Seat:seat-1]
xserver-command=/usr/bin/X :1
xserver-layout=seat-1

对于自动登录 multiseat (无显示管理器)

编辑脚本 /boot/twin.sh

#!/bin/bash
cmd1="/bin/bash --login -c \"/usr/bin/xinit --"
cmd2="-nolisten tcp -keeptty -novtswitch -config xorg.multiseat.conf"
usr=(user1 user2)  # FIXME: assume user1, user2 is valid user id
declare -a pid
while true ; do
  for ((i=0; i<${#usr[*]}; i++)) ; do
    echo "usr[$i]=${usr[$i]} pid=${pid[$i]}"
    if [ -z "${pid[$i]}" ] || [ ! -d "/proc/${pid[$i]}" ] ; then
      # echo "pid ${pid[$i]} killed, execute again"  
      cmd3="-layout seat$i vt0"$((7+i))"\""
      if [ $i -gt 0 ] ; then
        cmd3="-sharevts $cmd3"
      fi
      #echo "cmd3=$cmd3"
      /bin/su ${usr[$i]} -l -c "$cmd1 :$i $cmd2 $cmd3" &
      pid[$i]=$!
      #echo "new pid=${pid[$i]}"
    fi
  done
  sleep 5  # check process exist per 5 second
done

打开 /etc/inittab 并按如下方式设置

#id:3:initdefault:
id:5:initdefault:
...
x2:5:once:/root/twin.sh > /root/twin.log 2>&1

声音

每个 seat 一个声卡

一旦您连接声卡到 seat,Pulseaudio 将检测并使用它。

单个声卡上的多个用户:PulseAudio

如果两个用户想要同时使用声卡,则必须使用声音服务器,PulseAudio 是最流行的。 通常,PulseAudio 服务器仅为活动用户运行,并且不允许使用多个用户实例。 解决此问题的方法是使用系统范围的 PulseAudio 服务器。 尽管作者不鼓励使用这种方法,但这可能是最适用的设置。

为多个用户配置,无需系统模式守护进程

这将导致所有混音都转移到单个服务器。

将默认配置复制到主用户的 home 目录

$ cp /etc/pulse/default.pa ~/.pulse/

$ cp /etc/pulse/default.pa ~/.config/pulse/

编辑文件,在末尾添加

load-module module-native-protocol-tcp auth-ip-acl=127.0.0.1

如果 pulseaudio 已经在运行,请重启它

$ pulseaudio -k
$ pulseaudio --daemonize=no

为每个辅助用户重复此过程,以用户身份

$ echo "default-server = 127.0.0.1" > ~/.pulse/client.conf
为系统范围的 PulseAudio 配置
  • 创建用户 pulse 并将其放入组 audio(PulseAudio 会丢弃 root 权限并更改为用户 pulse。组成员身份允许访问设备。)
  • 创建组 pulse-access 并将将在本地播放声音的用户放入其中(组成员身份用于控制对 PA 守护进程的本地访问。)
  • 在 /etc/pulse/default.pa 中明确声明访问权限
load-module module-native-protocol-unix auth-group=pulse-access 
auth-group-enable=1

使用此内容创建 /etc/dbus-1/system.d/pulseaudio.conf /etc/dbus-1/system.d/pulseaudio.conf

<?xml version="1.0" encoding="UTF-8"?>
<busconfig>
	<policy user="pulse">
		<allow own="org.pulseaudio.Server"/>
		<allow send_destination="org.pulseaudio.Server"/>
		<allow receive_sender="org.pulseaudio.Server"/>
	</policy>
</busconfig>

以系统范围启动 PA,以 root 身份

# pulseaudio --system

/var/run/pulse 中应出现用于与守护进程通信的文件,即 pid 和 native。

用户访问

您可以检查与系统守护进程的非 root 通信,例如 pactl -s "unix:/var/run/pulse/native" list

可以在 /etc/pulse/client.conf 中启用自动网络连接到本地守护进程

auto-connect-localhost = yes

用户应该能够连接到 PA 服务器。 系统范围守护进程的所有缺点实际上都变成了优点,例如,能够控制 pavucontrol 中其他用户流的音量。

故障排除

可以在 /etc/pulse/default.pa 中启用 PA 的 http 接口以进行调试 load-module module-http-protocol-tcp,然后连接到 https://127.0.0.1:4714/

单个声卡上的多个用户:ALSA

设置删除了 PulseAudio,通过 alsamixer 均衡器和软件混音共享音频。 相关的硬件是 ATI Radeon HD 5850 和 Intel Sandy Bridge (板载) HD 3000。 配置步骤可能会有所不同。

可以在 /etc/asound.conf 中寻址特定硬件,以便在需要时同时为两个用户分配音频。 另一种选择是使两个不同的用户都能够使用音频和他们自己的均衡器(在下面进一步描述)。 声卡将在使用 ALSA 移除 PulseAudio 的情况下在 seat 之间平均共享 - 但是,libpulse 本身应保留用于各种软件依赖项。

接下来,删除各自的 ~/.asoundrc 文件(以及您删除的相关的 PulseAudio 配置文件),并按照此模板使用声音的 /etc/asound.conf

defaults.pcm.rate_converter "samplerate_best"

ctl.equal {
 type equal;
}

pcm.plugequal {
  type equal;
  # Modify the line below if you do not
  # want to use sound card 0.
  #slave.pcm "plughw:0,0";
  #by default we want to play from more sources at time:
  slave.pcm "plug:dmix";
}
#pcm.equal {
  # If you do not want the equalizer to be your
  # default soundcard comment the following
  # line and uncomment the above line. (You can
  # choose it as the output device by addressing
  # it with specific apps,eg mpg123 -a equal 06.Back_In_Black.mp3)
pcm.!default {
  type plug;
  slave.pcm plugequal;
}

只有最后一个登录的用户才能拥有音频控制和访问权限,但如果您希望在不同用户之间平均共享音频,请将每个用户添加到 audio 组

例子

usermod -a -G ftp joeblow
usermod -a -G ftp jillschmill

然后将此放入每个用户各自的 ~/.asoundrc 中,而不是使用 /etc/asound.conf(此选项还包含各种调整以提高音频质量)

defaults.pcm.rate_converter "samplerate_best"

ctl.equal {
 type equal;
}

pcm.ossmix {
    type dmix
    ipc_key 1024 # must be unique!
    ipc_key_add_uid false   # let multiple users share
    ipc_perm 0666           # IPC permissions for multi-user sharing (octal, default 0600)
    slave {
        pcm "hw:0,0"      # you cannot use a "plug" device here, darn.
        period_time 0
        period_size 1024 # must be power of 2.
        buffer_size 8192  # ditto.
        rate 44100
       #format "S32_LE"
       #periods 128 # dito.
       #rate 8000 # with rate 8000 you *will* hear,
       # if ossmix is used :)
    }
    # bindings are cool. This says, that only the first
    # two channels are to be used by dmix, which is
    # enough for (most) oss apps and also lets 
    # multichannel chips work much faster:
    bindings {
        0 0 # from 0 => to 0
        1 1 # from 1 => to 1
    }
}

pcm.plugequal {
  type equal;
  # Modify the line below if you do not
  # want to use sound card 0.
  #slave.pcm "plughw:0,0";
  #by default we want to play from more sources at time:
  slave.pcm "plug:ossmix";
}

#pcm.equal {
  # If you do not want the equalizer to be your
  # default soundcard comment the following
  # line and uncomment the above line. (You can
  # choose it as the output device by addressing
  # it with specific apps,eg mpg123 -a equal 06.Back_In_Black.mp3)
pcm.!default {
  type plug;
  slave.pcm plugequal;
}

可以使用以下命令访问均衡器

alsaequal -D equal

每个用户都有一个可以单独配置的均衡器。

确保调低并静音您不使用的音频通道,关闭麦克风自动静音,并确保没有通道的增益高于 0,以避免 ALSA 音频错误。 这可以通过 alsamixer 完成。

故障排除

Xorg 无法启动

查看 /var/log/Xorg.*.log 中的日志文件。 每个 seat 都会有一个。 阅读日志文件将向您展示 seat 尝试使用的设备,您可能会看到类似两个 seat 都在尝试使用同一显示设备的情况,因为您没有正确地将其分配给特定的 seat。

如果您正在使用显示管理器,请查明其日志文件在哪里,以便您可以检查它是否正确启动了 Xorg 服务器,并传递了所需的 -seat 参数。

我的 Windows 键不再工作

将此放入 启动文件

xmodmap -e "add Mod4 = Super_L Super_R"

不可靠的行为(黑屏无光标)

如果一切似乎都设置正确,但由于某种原因您总是得到黑屏无光标,请尝试将 BIOS 中初始化的第一张卡设置为 PCI 卡。

桌面上的小黑框/点

这实际上是虚拟终端的部分被绘制在 X 之上。 这似乎是由 Linux 内核帧缓冲器引起的。 这可以通过禁用帧缓冲器或从主 seat 的 X 参数中删除“-sharevts”选项来修复。

多媒体键不工作

如果您的键盘具有额外的“多媒体”键,您可能会发现它们在您的 multiseat 设置中停止工作。 这是因为此类键盘通常表示为多个“event”设备。 就像您在上面所做的那样,cat 每个 /dev/input/event* 设备,这次按下多媒体键。 找到正确的事件设备后,为其添加单独的键盘 InputDevice 部分,然后将该 InputDevice 部分添加到相应的 ServerLayout 部分,并使用 “SendCoreEvents” 选项,该选项指示应处理来自此设备的输入,即使它不是核心键盘。 最后,您应该有类似以下的部分

Section "InputDevice"
    Identifier      "Keyboard0"
    Driver          "evdev"
    Option          "Device" "/dev/input/event6"
    Option          "XkbModel" "evdev"
EndSection

Section "InputDevice"
    Identifier      "Keyboard0Multimedia"
    Driver          "evdev"
    Option          "Device" "/dev/input/event7"
    Option          "XkbModel" "evdev"
EndSection

Section "ServerLayout"
    Identifier     "Layout0"
    Screen      0  "Screen0" 0 0
    InputDevice    "Keyboard0" "CoreKeyboard"
    InputDevice    "Keyboard0Multimedia" "SendCoreEvents"
    InputDevice    "Mouse0" "CorePointer"
    Option         "AutoAddDevices" "no"
EndSection

Ctrl-Alt-Fx, Alt-Fx 键扰乱虚拟终端

(2010 年 10 月)我按照本指南操作,一切正常,除了 Atl-F1, Atl-F2,... 搞乱了东西。 然后我按照本指南 https://help.ubuntu.com/community/MultiseatX(阅读 Ubuntu 10.04 的部分)

# cd /usr/bin
# ln -s X X0
# ln -s X X1

然后在 /usr/share/config/kdm/kdmrc 中修复如下

[General]
ConsoleTTYs=tty1,tty2,tty3,tty4,tty5,tty6
ServerVTs=7,8
StaticServers=:0,:1
ReserveServers=:2,:3
...

[X-:0-Core]
ServerVT=8
ServerCmd=/usr/bin/X1
ServerArgsLocal=-nolisten tcp -sharevts -novtswitch -keeptty -layout Seat1 -isolateDevice PCI:1:0:0

[X-:1-Core]
ServerVT=7
ServerCmd=/usr/bin/X0
ServerArgsLocal=-nolisten tcp -novtswitch -keeptty -layout Seat0 -isolateDevice PCI:0:2:0
...

它适用于我的计算机:一块板载 Intel 卡(xf86-video-intel 驱动程序)和一块 Nvidia 卡(xf86-video-nouveau 驱动程序)。 您可以通过以下方式检查参数是否正确传递

$ pgrep -af PCI
root     16993  1.6  1.3  32900 26772 ?        S    08:09   0:19 /usr/bin/X0 :1 vt7 -nolisten tcp -novtswitch -keeptty -layout Seat0 -isolateDevice PCI:0:2:0 -auth /var/run/xauth/A:1-ES6CCb
root     17124  5.9  0.5  18996 11980 ?        S    08:09   1:09 /usr/bin/X1 :0 vt8 -nolisten tcp -sharevts -novtswitch -keeptty -layout Seat1 -isolateDevice PCI:1:0:0 -auth /var/run/xauth/A:0-Wgiyza

ServerVT=7, ServerVT=8 将作为 vt7, vt8 传递

使用 fbcon 内核参数修复 VT 行为

fbcon=map:n 传递给 内核命令行。(数字可能不同,请参阅 内核文档

上面的值导致 [Ctrl]+Alt+FX 在显卡编号 n 上切换,其他显卡仅显示 Xorg。

参见

  • 多指针 X 解释了如何在同一会话中设置两对独立的设备。