使用 ALSA 查找进程听起来很快

发布于 2024-07-12 22:42:40 字数 975 浏览 7 评论 0原文

目前,Debian 中的 /usr/sbin/alsa 识别使用声卡的进程的方式如下所示:

echo $( \
    lsof +D /dev -F rt \
    | awk '/^p/ {pid=$1} /^t/ {type=$1} /^r0x(74|e)..$/ && type == "tCHR" {print pid}' \
    | cut -c 2- \
    | uniq \
)

这是相当难看的,并且依赖于 lsof。 我正在寻找一个没有 lsof 的 POSIX 解决方案,也许使用 /proc。

    time for i in /proc/*/fd/*; do readlink $i | grep -q /dev/snd/pcm && echo $i | awk -F '/' '{print $3}'; done | uniq

不幸的是,似乎需要比上面基于 lsof 的代码片段长两倍的时间。 你能否让它更快,以使其成为可行的替代品?

更新我将上面的内容重写为:

#!/bin/sh
for i in /proc/[0-9]*/fd/*
do
        if readlink $i | grep -q /dev/snd/pcm
        then
                IFS=/; set -- $i; unset IFS; echo $3
        fi
done

但它似乎与我之前的代码片段具有相同的性能。 我怀疑 grep 是罪魁祸首。

更新:我已经针对该主题打开了 Debian bug

Currently the way /usr/sbin/alsa in Debian knows the processes using the sound card looks like:

echo $( \
    lsof +D /dev -F rt \
    | awk '/^p/ {pid=$1} /^t/ {type=$1} /^r0x(74|e)..$/ && type == "tCHR" {print pid}' \
    | cut -c 2- \
    | uniq \
)

Which is rather ugly and depends on lsof. I am looking for a POSIX solution without lsof, perhaps using /proc.

    time for i in /proc/*/fd/*; do readlink $i | grep -q /dev/snd/pcm && echo $i | awk -F '/' '{print $3}'; done | uniq

Unfortunately seems to take twice as long as the lsof based snippet above. Can you make it faster, in order to make it a viable replacement?

Update I rewrote the above as:

#!/bin/sh
for i in /proc/[0-9]*/fd/*
do
        if readlink $i | grep -q /dev/snd/pcm
        then
                IFS=/; set -- $i; unset IFS; echo $3
        fi
done

But it seems to have the same performance as my earlier snippet. I suspect grep is the culprit.

Update: I have opened a Debian bug on the topic.

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

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

发布评论

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

评论(3

回梦 2024-07-19 22:42:40

这个问题的答案 ALSA 常见问题解答。 在我的系统上,使用 fusionr 比使用 lsof 快得多。

fuser -v /dev/snd/*

There is an answer for this question on the ALSA FAQ. On my system, using fuser is way faster than using lsof.

fuser -v /dev/snd/*
天涯沦落人 2024-07-19 22:42:40

您在这里启动了很多进程。 相反,您可以尝试以与您发布的 lsof 脚本类似的方式进行操作...但将 lsof 替换为 shell for 循环:

如果您想避免启动大量 grep 进程,请仅启动一个:

#!/bin/sh
for i in /proc/[0-9]*/fd/*
do
    echo ${i%/fd/*} $(readlink $i)
done | grep -q /dev/snd/pcm

这在我的桌面上现在需要 4.5 秒,相比之下,每个打开的文件都有一个 grep 进程时需要 7.5 秒。

但是......我认为你的 grep 在这里是不必要的。 如果你很在意,你可以尝试:

#!/bin/sh
for i in /proc/[0-9]*/fd/*
do
    var="$(readlink $i)"
    if test x"$var" != x"${var#/dev/snd/pcm}"
    then
        echo $i
    fi
done

这对我来说甚至更快(test几乎总是内置的shell),但我想这更多是因为糟糕的测试方法。 自己尝试一下。

You start a lot of processes here. Instead you can try doing in a similar way to the lsof script you posted... but replacing lsof by a shell for loop:

If you want to avoid launching lots of grep processes, start only one:

#!/bin/sh
for i in /proc/[0-9]*/fd/*
do
    echo ${i%/fd/*} $(readlink $i)
done | grep -q /dev/snd/pcm

This takes now 4.5s on my desktop, compared to 7.5s when there's one grep process for each opened file.

But... your grep is not necessary here, I think. If you care so much, you can try:

#!/bin/sh
for i in /proc/[0-9]*/fd/*
do
    var="$(readlink $i)"
    if test x"$var" != x"${var#/dev/snd/pcm}"
    then
        echo $i
    fi
done

This is even faster for me (test is almost always a shell builtin), but I guess this is more because of bad testing methods. Try yourself.

迷你仙 2024-07-19 22:42:40

您没有说明您正在寻找什么样的时间尺度,但您的替代建议

for i in /proc/[0-9]*/fd/*;

可能会起作用并给您带来一点速度,就像使用 cut 而不是 awk

You don't say what kind of timescales you're looking for but for your alternative suggestion

for i in /proc/[0-9]*/fd/*;

might work and give you a bit of speed up, as might using cut rather than awk.

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