Nie jesteś zalogowany.
Jeśli nie posiadasz konta, zarejestruj je już teraz! Pozwoli Ci ono w pełni korzystać z naszego serwisu. Spamerom dziękujemy!

Ogłoszenie

Prosimy o pomoc dla małej Julki — przekaż 1% podatku na Fundacji Dzieciom zdazyć z Pomocą.
Więcej informacji na dug.net.pl/pomagamy/.

#1  2013-05-05 02:32:20

  morfik - Cenzor wirtualnego świata

morfik
Cenzor wirtualnego świata
Skąd: ze WSI
Zarejestrowany: 2011-09-15
Serwis

Przeładowanie modułów jądra

Analizując skrypt alsy:

Kod:

#!/bin/sh
#
# alsa-base control script
#
# Description: Used to load and unload ALSA modules and
#              restore and store mixer levels. There is no
#              longer any need to run this script on bootup
#              or shutdown. It is now moved to /usr/sbin.

set -e

# Exit if alsa-base package is not installed
[ -f /etc/modprobe.d/alsa-base.conf ] || exit 0

MYNAME=/usr/bin/alsa.sh
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# Default values of variables in /etc/default/alsa
force_unload_modules_before_suspend=""

[ -f /etc/default/alsa ] && . /etc/default/alsa

# $* MESSAGE
warn() { echo "${MYNAME}: Warning: $* " >&2 ; }

#
# Attempt to create /var/run/alsa if it is absent.
# Return true if /var/run/alsa exists after this attempt,
# otherwise false.
#
check_run_dir()
{ 
    [ -d /var/run/alsa ] && return 0
    # We have no business creating /var/run if it doesn't exist
    if ! [ -d /var/run ] ; then
        warn "Could not create /var/run/alsa/ because /var/run/ is not present."
        return 1
    fi
    if ! mkdir --mode=755 /var/run/alsa ; then
        warn "Failed to create /var/run/alsa/."
        return 1
    fi
    [ -d /var/run/alsa ] && return 0
    return 1
}

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

# $* [PID]...
echo_with_command_names()
{
    [ "$1" ] || return 0
    echo $( \
        ps --no-headers -o "%p %c" "$@" \
        | sed -e 's/\([0-9][0-9]*\) \(.*\)/\1(\2)/' \
    )
}

kill_procs_using_sound()
{
    procs_using_sound="$(echo_procs_using_sound)"
    if [ "$procs_using_sound" ] ; then
        echo -n "Terminating processes:"
        for attempt in 1 2 3 4 ; do
            echo -n " ${procs_using_sound}"
            kill $procs_using_sound || :
            sleep 1
            procs_using_sound="$(echo_procs_using_sound)"
            [ "$procs_using_sound" ] || break
        done
        # Either no more procs using sound or attempts ran out
        if [ "$procs_using_sound" ] ; then
            echo -n " (with SIGKILL:) ${procs_using_sound}"
            kill -9 $procs_using_sound || :
            sleep 1
        fi
        procs_using_sound="$(echo_procs_using_sound)"
        if [ "$procs_using_sound" ] ; then
            echo " (failed: processes still using sound devices: $(echo_with_command_names $procs_using_sound))."
            return 1
        fi
        echo "."
    fi
    return 0
}

# $* MODULE-NAME [MODULE-NAME]... | "all"
unload_modules()
{
    procs_using_sound="$(echo_procs_using_sound)"
    if [ "$procs_using_sound" ] ; then
        warn "Processes using sound devices: $(echo_with_command_names $procs_using_sound)."
    fi
    if check_run_dir ; then
        :> /var/run/alsa/modules-removed
    else
        warn "Not keeping list of removed modules because /var/run/alsa is absent.
It will not be possible automatically to reload these modules."
    fi
    echo -n "Unloading ALSA sound driver modules:"
    [ -d /proc/asound ] || { echo " (none loaded)." ; return 0 ; }
    echo_snd_modules_loaded()
    {
        lsmod \
        | sed -n -e 's/^\(snd[-_][^[:space:]]*\)[[:space:]].*/\1/p' \
        | sed -e 's/_/-/g'
    }
    for FSMBS in $* ; do
        MODULES_TO_REMOVE=""
        SND_MODULES_LOADED="$(echo_snd_modules_loaded)"
        case "$FSMBS" in
          all)
            MODULES_TO_REMOVE="$SND_MODULES_LOADED"
            ;;
          snd_*|snd-*)
            FSMBS="$(echo "$FSMBS" | sed -e 's/_/-/g')"
            for M in $SND_MODULES_LOADED ; do
                if [ "$FSMBS" = "$M" ] ; then
                    MODULES_TO_REMOVE="$FSMBS"
                    break
                fi
            done
            ;;
        esac
        [ "$MODULES_TO_REMOVE" ] || continue
        if [ -d /var/run/alsa ] ; then
            echo "$MODULES_TO_REMOVE" >> /var/run/alsa/modules-removed
        fi
        for M in $MODULES_TO_REMOVE ; do
            echo -n " ${M}"
            modprobe -r "$M" >/dev/null 2>&1 || :
        done
    done
    if [ -f /var/run/alsa/modules-removed ] ; then
        MODULES_STILL_LOADED="$(echo_snd_modules_loaded | grep -F -f /var/run/alsa/modules-removed)"
        MODULES_STILL_LOADED="$(echo $MODULES_STILL_LOADED)"
    else
        MODULES_STILL_LOADED=""
    fi
    if [ "$MODULES_STILL_LOADED" ] ; then
        echo " (failed: modules still loaded: ${MODULES_STILL_LOADED})."
        return 1
    else
        echo "."
        return 0
    fi
}

# $* MODULE-NAME [MODULE-NAME]... | "all"
force_unload_modules()
{
    kill_procs_using_sound || :
    unload_modules "$@" || return 1
    return 0
}

load_unloaded_modules()
{
    LUM_RETURNSTATUS=0
    MODULES_TO_LOAD=""
    [ -d /var/run/alsa ] || warn "Directory /var/run/alsa is absent."
    echo -n "Loading ALSA sound driver modules:"
    [ -f /var/run/alsa/modules-removed ] && MODULES_TO_LOAD="$(echo $(cat /var/run/alsa/modules-removed))"
    [ "$MODULES_TO_LOAD" ] || { echo " (none to reload)." ; return $LUM_RETURNSTATUS ; }
    echo -n " $MODULES_TO_LOAD"
    for MDL in $MODULES_TO_LOAD ; do
        modprobe $MDL || LUM_RETURNSTATUS=1
    done
    case "$LUM_RETURNSTATUS" in
      0) echo "." ;;
      *) echo " (failed)." ;;
    esac
    return $LUM_RETURNSTATUS
}

case "$1" in
  unload)
    unload_modules all || exit $?
    ;;
  reload)
    EXITSTATUS=0
    unload_modules all || EXITSTATUS=1
    load_unloaded_modules || EXITSTATUS=1
    exit $EXITSTATUS
    ;;
  force-unload)
    force_unload_modules all || exit $?
    ;;
  force-reload)
    EXITSTATUS=0
    force_unload_modules all || EXITSTATUS=1
    load_unloaded_modules || EXITSTATUS=1
    exit $EXITSTATUS
    ;;
  suspend)
    case "$force_unload_modules_before_suspend" in
      ""|false) : ;;
      all|true) force_unload_modules all || exit $? ;;
      *) force_unload_modules $force_unload_modules_before_suspend || exit $? ;;
    esac
    ;;
  resume)
    case "$force_unload_modules_before_suspend" in
      ""|false) : ;;
      *) load_unloaded_modules || exit $? ;;
    esac
    ;;
  *)
    echo "Usage: $MYNAME {unload|reload|force-unload|force-reload|suspend|resume}" >&2
    exit 3
    ;;
esac

na myśl mi przyszły dwa pytania:

1. jak uzyskać informacje, jaki proces lub coś innego korzysta z modułu?
2. czy da się jakoś siłowo usunąć moduł z jądra?

Chodzi o to, że ten powyższy skrypt rozwiązuje problemu z dźwiękiem przez przeładowanie modułów dźwiękowych. Nie było go co prawda na archu ale go pożyczyłem z debiana i po niezbyt głębokiej analizie rzuciły mi się w oczy następujące kroki: Pobranie numeru procesu używającego dźwięk, ubicie procesów, wylistowanie modułów snd* i usinięcie ich z jądra.

Problem się zaczyna w momencie gdy próbowałem to ręcznie zrobić -- konkretnie przez zamykanie aplikacji odtwarzające dźwięk. Jednak przy próbie usunięcia modułu, dostałem poniższy komunikat:

Kod:

root:/home/morfik# modprobe -r snd-ca0106
modprobe: FATAL: Module snd_ca0106 is in use.

Sprawdziłem zatem funkcją ze skryptu czy może jakiś proces używa modułu ale nic nie wskazało. Jednak coś używało tego modułu, był to oczywiście pulse. xD Po wydaniu pulseaudio -k moduł się dał usunąć.

Offline

 

#2  2013-05-05 06:17:07

  Jacekalex - Podobno człowiek...;)

Jacekalex
Podobno człowiek...;)
Skąd: /dev/random
Zarejestrowany: 2008-01-07

Re: Przeładowanie modułów jądra

Kod:

lsof /dev/dsp* /dev/audio* /dev/mixer* /dev/snd/*

Każda karta dźwiękowa, graficzna, czy inny sprzęt  jest reprezentowana przez urządzenie w /dev.

Korzystanie z danego sterownika polega na komunikacji programu  z urządzeniem przypisanym do danego sterownika.

To by było na tyle
;-)

Ostatnio edytowany przez Jacekalex (2013-05-05 06:20:00)


W demokracji każdy naród ma taką władzę, na jaką zasługuje ;)
Si vis pacem  para bellum  ;)       |       Pozdrawiam :)

Offline

 

#3  2013-05-05 15:55:32

  morfik - Cenzor wirtualnego świata

morfik
Cenzor wirtualnego świata
Skąd: ze WSI
Zarejestrowany: 2011-09-15
Serwis

Re: Przeładowanie modułów jądra

Ok, pulse jest tam widoczny:

Kod:

root:~# lsof /dev/dsp* /dev/audio* /dev/mixer* /dev/snd/*
lsof: status error on /dev/dsp*: No such file or directory
lsof: status error on /dev/audio*: No such file or directory
lsof: status error on /dev/mixer*: No such file or directory
COMMAND    PID   USER   FD   TYPE DEVICE SIZE/OFF  NODE NAME
pulseaudi 6900 morfik  mem    CHR  116,7          26304 /dev/snd/pcmC0D1p
pulseaudi 6900 morfik  mem    CHR  116,9          26306 /dev/snd/pcmC0D0p
pulseaudi 6900 morfik   21u   CHR 116,11      0t0 26308 /dev/snd/controlC0
pulseaudi 6900 morfik   22r   CHR 116,33      0t0  2720 /dev/snd/timer
pulseaudi 6900 morfik   23u   CHR  116,9      0t0 26306 /dev/snd/pcmC0D0p
pulseaudi 6900 morfik   24u   CHR  116,7      0t0 26304 /dev/snd/pcmC0D1p
pulseaudi 6900 morfik   25r   CHR 116,33      0t0  2720 /dev/snd/timer
pulseaudi 6900 morfik   30u   CHR 116,11      0t0 26308 /dev/snd/controlC0

Polecenie było troszkę obcięte. Dodałem mu tam parametr +c ale przy lsof +c 16 nic nie jest pokazywane. Da radę ustawić więcej niż  +c 15?

W każdym razie, da radę ubić tam procesy używające karty i uwolnić moduł:

Kod:

kill -9 `lsof -t /dev/dsp* /dev/audio* /dev/mixer* /dev/snd/*`

Czyli jedno pytanie z głowy. A co w przypadku drugiego? Da radę usunąć siłowo moduł z jądra bez ubijania procesów? Czy jest to niewykonalne i trzeba pierw ubić procesy wykorzystujące moduł?

Offline

 

Stopka forum

Powered by PunBB
© Copyright 2002–2005 Rickard Andersson
Możesz wyłączyć AdBlock — tu nie ma reklam ;-)