Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Applications muti-thread/fork

7 réponses
Avatar
xavier
Bonjour,

J'ai une appli qui utilise plusieurs processus shell.

Chque processus est bien entendu identique, sauf aux données qu'il doit
traiter. C'est le rendu de ces données qui pose problème si je ne veux
pas avoir mes beaux tableaux ASCII intriqués les uns dans les autres.

Ce que je fais c'est que chaque traitement écrit dans un fichier temp,
et à la fin, je demande un sémaphore exclusif (que je peux
éventuellement attendre) sur le fichier de résultats, j'y appende les
résultats de la tâche, je lache le sémaphore, et j'attends le jeu de
données suivantes. Comme ça, tous les résultats sont bien séparés.

Est-ce une méthode correcte ? Chez moi, ça tourne sans problème depuis
10 ans avec des concurrences jusqu'à 30. Mais il y aurait mieux ?

Merci,

--
XAv
In your pomp and all your glory you're a poorer man than me,
as you lick the boots of death born out of fear.
(Jethro Tull)

7 réponses

Avatar
Alain Montfranc
Il se trouve que Xavier a formulé :
Bonjour,

J'ai une appli qui utilise plusieurs processus shell.

Chque processus est bien entendu identique, sauf aux données qu'il doit
traiter. C'est le rendu de ces données qui pose problème si je ne veux
pas avoir mes beaux tableaux ASCII intriqués les uns dans les autres.

Ce que je fais c'est que chaque traitement écrit dans un fichier temp,
et à la fin, je demande un sémaphore exclusif (que je peux
éventuellement attendre) sur le fichier de résultats, j'y appende les
résultats de la tâche, je lache le sémaphore, et j'attends le jeu de
données suivantes. Comme ça, tous les résultats sont bien séparés.

Est-ce une méthode correcte ? Chez moi, ça tourne sans problème depuis
10 ans avec des concurrences jusqu'à 30. Mais il y aurait mieux ?

Merci,



Ca semble bien... L'autre solution serait de faire communiquer chaque
fils avec son père, charge à ce dernier de traiter les resultats reçus
un par un, ce qui aurait l'avantage de permettre une ecrire sur stdout
(quoi que tes fils peuvent partager le meme stdout)

Seul risque à mon avis : le plantage d'un fils alors que le semaphore
est leve ==> les autres attendrons indéfiniment
Avatar
xavier
Alain Montfranc wrote:

Seul risque à mon avis : le plantage d'un fils alors que le semaphore
est leve ==> les autres attendrons indéfiniment



Celui-là, je le gère aussi : si j'attends plus de 5 fois la durée maxi
estimée d'une éxécution normale, je force le sémaphore.

Merci,

--
XAv
In your pomp and all your glory you're a poorer man than me,
as you lick the boots of death born out of fear.
(Jethro Tull)
Avatar
Nicolas George
Xavier, dans le message <1kar63q.13qkseej9peqyN%, a
écrit :
Ce que je fais c'est que chaque traitement écrit dans un fichier temp,
et à la fin, je demande un sémaphore exclusif (que je peux
éventuellement attendre) sur le fichier de résultats, j'y appende les
résultats de la tâche, je lache le sémaphore, et j'attends le jeu de
données suivantes. Comme ça, tous les résultats sont bien séparés.



C'est correct en théorie. Cependant, tu devrais préciser quel type de
sémaphore tu utilises, parce que certaines API sont une calamité.
Avatar
xavier
Nicolas George <nicolas$ wrote:

C'est correct en théorie. Cependant, tu devrais préciser quel type de
sémaphore tu utilises, parce que certaines API sont une calamité.



Comme c'est du script shell, j'utilise un sémaphore au niveau du FS,
lockfile(1), plus souple que lockf(1), même si son implémentation ne
garantit pas stricto sensu l'atomicité, en tout cas ça n'est pas précisé
dans la manpage.

En Perl, j'utilise plutôt POSIX::RT::Semaphore

Merci,

--
XAv
In your pomp and all your glory you're a poorer man than me,
as you lick the boots of death born out of fear.
(Jethro Tull)
Avatar
Nicolas George
Xavier, dans le message <1karuxz.1kq5k29db4zxjN%, a
écrit :
Comme c'est du script shell, j'utilise un sémaphore au niveau du FS,
lockfile(1), plus souple que lockf(1), même si son implémentation ne
garantit pas stricto sensu l'atomicité, en tout cas ça n'est pas précisé
dans la manpage.



C'est raisonnable. Mais tu aurais plutôt dû parler de verrou que de
sémaphore, la sémantique n'est pas exactement la même.
Avatar
xavier
Nicolas George <nicolas$ wrote:

la sémantique n'est pas exactement la même.



Exact. Merci de la précision.

--
XAv
In your pomp and all your glory you're a poorer man than me,
as you lick the boots of death born out of fear.
(Jethro Tull)
Avatar
Cyrille Lefevre
Le 15/11/2011 11:48, Xavier a écrit :
Nicolas George<nicolas$ wrote:

C'est correct en théorie. Cependant, tu devrais préciser quel type de
sémaphore tu utilises, parce que certaines API sont une calamité.



Comme c'est du script shell, j'utilise un sémaphore au niveau du FS,
lockfile(1), plus souple que lockf(1), même si son implémentation n e
garantit pas stricto sensu l'atomicité, en tout cas ça n'est pas pr écisé
dans la manpage.

En Perl, j'utilise plutôt POSIX::RT::Semaphore



Bonjour,

perso, j'aime bien ln ou mkdir :

http://groups.google.com/group/fr.comp.os.unix/msg/b445bc0bbafcd508?hl= fr

PS : bon, là, d'accord, j'me suis éclaté à implémenter siglal e t atexit
en shell, le principal étant la function lock() à base de ln.

attention, les fichiers doivent être dans le même sens, ex. :
proc 1 : lock a b c
proc 2 : lock a c
proc 3 : lock b c
et non proc 2 : lock c a, sinon, opssibilité de deadlock

un autre version de la function lock avec timeout plus adapté (retry si
un nouveau lock a été posé dans l'interal d'attente) sans tout le t outim
autour est :

trace() { echo typeset trace=: ; }
function _lock # file [timeout] [sleeptime] [checktime]
{
set +x; eval $(trace -q _lock "$@")

typeset file=$1 timeout=$2 sleeptime=$3 checktime=$4
typeset dir="${TMPDIR:-${_VARTMP}}"

if [[ -z ${file} ]]; then
file="${dir}/${_PROGNAME}"
elif [[ ${file} != *'/'* ]]; then
file="${dir}/${file}"
fi

if [[ -z ${timeout} ]]; then
timeout="${TIMEOUT_LOCK_GLOBAL:-60}"
fi

if [[ -z ${sleeptime} ]]; then
if (( timeout > 10 )); then
sleeptime
elif (( timeout < 0 )); then
sleeptime=5
else
sleeptime=1
fi
fi

if [[ -z ${checktime} ]]; then
if (( timeout <= 0 )); then
checktime="${timeout}"
else
checktime="${TIMEOUT_LOCK_GLOBAL:-60}"
fi
fi

( # portable EXIT trap
typeset lock="${file}.lck" temp="${file}.$$"

trap '${_RM} -f "${temp}"' EXIT

${_TOUCH} "${temp}"
integer rc=$?

if (( rc == 0 )); then
if (( checktime > 0 )); then
integer difftime=$(${_FCDATE} -d "${temp}"
"${lock}")
if (( difftime > checktime )); then
${_RM} -f "${lock}"
fi
fi
integer time0="${SECONDS}"
(( time0 -= 1 ))
until ${DEVNULL2} ${_LN} "${temp}" "${lock}"; do
if (( timeout == 0 )); then
rc=1
break
fi
if (( timeout > 0 && ( SECONDS - time0 ) >
timeout )); then
if (( checktime > 0 )); then
difftime=$(${_FCDATE} -d
"${temp}" "${lock}")
time0="${SECONDS}"
(( time0 -= 1 ))
if (( difftime < 0 )); then
continue
elif (( difftime > checktime
)); then
${_RM} -f "${lock}"
continue
fi
else
rc=1
break
fi
fi
sleep "${sleeptime}"
${_TOUCH} "${temp}"
done
fi
)
set +x; eval ${trace}
return ${rc}
}

function _unlock # file...
{
set +x; eval $(trace -q _unlock "$@")

typeset file=$1
typeset dir="${TMPDIR:-/var/tmp}"

if [[ -z ${file} ]]; then
file="${dir}/${_PROGNAME}"
elif [[ ${file} != *'/'* ]]; then
file="${dir}/${file}"
fi

typeset lock="${file}.lck"
${_RM} -f "${lock}"

set +x; eval ${trace}
return 0
}


Cordialement,

Cyrille Lefevre.
--
mailto:Cyrille.Lefevre-news%
supprimer "%nospam% et ".invalid" pour me repondre.