Как создать процесс в Linux?

El uso de seden ese fragmento de código es analizar la salida de wc -lpara extraer el número de líneas en el archivo.

Esto normalmente no es necesario ya que

l=$( wc -l <"$f" )

habría hecho lo mismo (deberías probar esto ).


La secuencia de comandos utiliza algunas construcciones que no son -portátiles y se consideran "obsoletas", y hay detalles en la secuencia de comandos que la hacen insegura.

  1. Deben citarse las ampliaciones. Por ejemplo, if [ $# -lt 1 ]se escribe mejor como if [ "$#" -eq 0 ]y if [ -O $f ]debería ser if [ -O "$f" ]. De esta forma, podemos admitir nombres de archivos que contengan cualquier carácter, incluso caracteres que formen parte de$IFS(espacios, tabulaciones y saltos de línea ). El $#debe citarse en caso de que $IFScontenga dígitos por algún motivo u otro.

    Para obtener más información sobre esto, consulte las otras tres preguntas tituladas " Implicaciones de seguridad de olvidar citar una variable en shells bash/POSIX ", " ¿Por qué mi script de shell se ahoga con espacios en blanco u otros caracteres especiales? " y " ¿Cuándo es necesario -comillas dobles? ".

  2. La sustitución de comandos mediante acentos graves es problemática en algunas circunstancias. La línea que dice l=`wc -l...`podría reescribirse como l=$(wc -l...). El $(...)más nuevo es mejor ya que anida, ya que las citas funcionan como se esperaba (compare, p. echo "`echo "`echo ok`"`", lo que genera un error de sintaxis, con echo "$(echo "$(echo ok)")"), y ya que es más fácil de leer.

    Para obtener más información sobre esto, véase, p. " ¿Han quedado obsoletos los backticks (, es decir, `cmd `)en *sh shells? "

  3. $[ $s + $l ]es una forma no -portable de decir $(( s + l )).

  4. Los datos variables deben generarse usando printfen lugar de usar echo. Por ejemplo, esa última línea,

    echo "$n files in total, with $s lines in total"
    

    puede reescribirse como

    printf '%d files in total, with %d lines in total\n' "$n" "$s"
    

    Véase, p. " ¿Por qué printf es mejor que echo? ".

  5. El uso de $*para recorrer los argumentos de la línea de comando detiene el funcionamiento del script en los nombres de archivo que contienen espacios.

  6. La declaración continuey la rama elsede la declaración ifno son necesarias en absoluto, ya que de todos modos son las últimas en el bucle.

  7. La ​​salida de diagnóstico debe imprimirse con un error estándar.

Versión "corregida" del script:

#!/bin/bash
# Counting the number of lines in a list of files
# for loop over arguments
# count only those files I am owner of

if [ "$#" -eq 0 ]; then
    printf 'Usage: %s file...\n' "$0" >&2
    exit 1
fi

printf '%s counts the lines of code\n' "$0"
l=0; n=0; s=0
for name do
    if [ -f "$name" ] && [ -O "$name" ]; then # checks whether its a regular file and file owner is running the script
        nlines=$( wc -l <"$name" )
        printf '%s: %d\n' "$name" "$nlines"
        totlines=$(( totlines + nlines ))
        nfiles=$(( nfiles + 1 ))
    fi
done

printf '%d files in total, with %s lines in total" "$nfiles" "$totlines"

0
22.06.2019, 11:58
1 ответ

При создании нового процесса родительский процесс должен нести ответственность за любые ресурсы, потребляемые новым процессом с -по -, пока он фактически не станет -автономным процессом. Справиться с этим, вероятно, будет сложнее, чем с поведением fork(), но, как сказал @炸鱼薯条德里克 в комментариях, существует системный вызов clone(), который позволяет вам лучше контролировать особенности поведения создание потока/процесса.

Системный вызов fork()на самом деле максимально избегает копирования памяти за счет использования копирования -в управлении записью -памяти. Когда fork()выполняется,как новый процесс, так и его родитель будут первоначально обращаться к одной и той же памяти (только таблицы страниц родительского процесса фактически копируются изначально ), но эта память помечена как Копировать -на -Запись для блок управления памятью процессора. Если дочерний процесс немедленно использует execve()для загрузки новой программы, дочерний процесс получает свое собственное выделение памяти как часть execve()и родительского Копия -на -Ограничение записи снимается :оптимизация работает как предполагалось.

Но если либо родительский, либо дочерний процесс модифицирует какую-либо из временно -страниц разделяемой памяти до того, как дочерний процесс выполнит execve(), то бит копирования -на -записи вызовет ошибку страницы перед записью. фактически продолжается, ядро ​​делает вторую копию страницы памяти, которая будет изменена, а затем и родительский, и дочерний процессы получают свои собственные, обычные, доступные для записи копии этой страницы памяти с ожидаемым содержимым. Таким образом, если процесс использует fork()без execve(), фактическое копирование происходит позже, с гранулярностью -памяти -страниц, в соответствии с тем, какие страницы фактически записываются.

Системный вызов vfork()делает эту оптимизацию явной :родительский процесс/поток приостанавливается при выполнении vfork()до тех пор, пока дочерний процесс не вызовет execve()или _exit(). Прежде чем vfork()ed дочерний процесс выполнит execve(), он должен ограничить себя тем, что не будет выполнять определенные действия. Это сводит к минимуму вероятность того, что любое копирование памяти необходимо.

Насколько я знаю, кроме системных вызовов fork(), vfork()и clone()нет другого способа создавать новые процессы из пользовательского пространства. Если вы находитесь в коде ядра, могут быть доступны разные параметры, в зависимости от того, в какой именно части ядра вы находитесь.

0
28.01.2020, 03:35

Теги

Похожие вопросы