Question

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.

Was it helpful?

Solution

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.

OTHER TIPS

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/*

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top