Что делать с "ls -l *c"?
Клейтон Кристиан и Блейк Уиллис

Итак, что такое оболочка?

В некоторых системах оболочка также упоминается как интерпретатор команд. Это определение описывает, что оболочка представляет собой уровень программирования, который понимает и выполняет команды, которые вводит пользователь. Это ты — пользователь! Итак, оболочка — это то, с чем вы будете разговаривать при вводе команд.

Также важно понимать, что такое оболочка по отношению к ядру.

Ядро является фундаментальной частью компьютерной системы. Это сама программа, и она управляет любой другой программой на компьютере. Ядро взаимодействует с аппаратным и программным обеспечением. Он также отвечает за управление ресурсами.

Оболочка, как интерпретатор командной строки Linux, предоставляет пользователю интерфейс для связи с ядром и выполнения программ, называемых командами. Его также иногда называют «пользовательским пространством». Чтобы программа запустилась, оболочка должна передать ее ядру. Например, если бы мы хотели вывести список файлов и подкаталогов определенного каталога, мы бы передали в нашу оболочку команду Bash («оболочка Bourne-again») «ls».

Мы можем сделать более сложный запрос к ядру, используя различные аргументы и опции, присоединенные к команде. Давайте подробнее остановимся на этом.

Теперь об этой команде «ls -l *c».

Команда «ls -l *c» на первый взгляд может показаться пугающей, но она очень похожа на базовую команду «ls», на которую мы ссылались в предыдущих абзацах. Вот его разбивка:

«Ls *c» — это команда для вывода списка всех файлов и каталогов в текущем каталоге, которые заканчиваются расширением файла «.c». «Текущий каталог» — это процесс в иерархической файловой системе. Расширение — это идентификатор файла в операционной системе. Linux/Unix — это операционные системы. Символ «*» означает соответствие любым символам в имени файла.

С опцией '-l' 'ls *c' будет перечислять файлы и каталоги с расширением .c (что означает, что файлы заканчиваются на '.c') в формате длинного списка, который включает их соответствующие разрешения, владельцев и созданные файлы. Дата и время. Ввод этой полной команды и нажатие Enter вернет список запрошенных нами файлов.

Теперь, когда мы дали краткий обзор того, что происходит, когда мы вызываем команду «ls», давайте перейдем к более подробному пошаговому описанию того, что происходит с нашим ядром и оболочкой во время этих процессов. Пройдемся по порядку действий:

1. Оболочка считывает команду с помощью функции «getline()». Shell написана в основном на языке программирования C. Функция «getline()» — это стандартная функция C, которая, как следует из ее названия, получает строку откуда бы она ни была задана, в нашем случае из командной строки оболочки.

2. Bash как интерпретатор команд проверяет, есть ли специальные слова в его собственном языке: то есть ключевые слова оболочки или встроенные в оболочку (ls не входит в число ключевых слов оболочки). Bash как интерпретатор команд проверяет, есть ли такие специальные слова в его собственном языке: ключевые слова оболочки или встроенные в оболочку (ls нет среди ключевых слов оболочки, затем он проверяет псевдонимы и заменяет псевдоним своим значением).

3. он ищет исполняемый файл ls по путям, указанным в переменной PATH env. Обычно это /bin/ls.

4. Он разветвляет (fork()) новый процесс и выполняет его код (exec()). Процесс env наследуется от родительского процесса новому процессу ls.

5. Новый процесс становится лидером сеанса и начинает работать на переднем плане (обращение уходит на задний план).

6. Печатает вывод и завершает работу, отправляет сигнал wait(), и родительский процесс bash полностью его завершает.

7. После выполнения команды «ls» оболочка выполняет команды завершения работы, освобождает память и повторно запрашивает ввод данных пользователем.

Под поверхностью..

Итак, теперь, когда мы изучили методологию выполнения ввода команды как функции, мы можем и должны немного глубже взглянуть на некоторые процессы, происходящие «под капотом».

После того, как мы вводим команду в оболочку, она считывает команду ls -l.c*, используя данные STDIN функции getLine(). После этого ввод сохраняется в буфере в виде строки.

Буфер теперь может считывать из STDIN в соответствии с заданным размером блока и записывать каждый блок в стандартный вывод.

Строка теперь делится на части (токены) с помощью разделителя путем удаления пробелов, а затем сохраняется в массиве строк.

Оболочка проверяет, имеет ли какой-либо из токенов определенный псевдоним. Если есть, он заменяет токен своим значением.

Если нет, он проверяет, является ли какой-либо из токенов встроенной функцией, и если его там нет.

Оболочка ищет программный файл с именем ls в среде оболочки, где все исполняемые файлы находятся в системе, в частности, в переменной $PATH. Переменная $PATH представляет собой список каталогов, которые оболочка ищет при каждом вводе команды. Одна из переменных среды, $PATH, анализируется с использованием «=» в качестве разделителя. Как только $PATH идентифицирован, все каталоги в $PATH токенизируются, каждое местоположение указывается с помощью разделителя «:», рекурсивный поиск путем добавления команды в конце пути.

Поскольку он ищет рекурсивно, он сначала будет искать в pwd, затем в его родительском элементе, и так далее, и так далее со всеми остальными командами.

Для выполнения ls выполняются следующие системные вызовы: fork(), execve() и wait().

Системные вызовы — это взаимодействие, которое мы совершаем с ядром.

Чтобы запустить команду в оболочке, выполняется системный вызов fork(), который дублирует оболочку, создавая дочернюю оболочку родительской оболочки.

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

Между тем, используя системный вызов wait(), родительский процесс продолжает отслеживать своих дочерних процессов в фоновом режиме.

После выполнения команды ls -l.c* оболочка освобождает память, завершает работу и снова предлагает пользователю ввести данные.

В большинстве случаев все это происходит менее чем за несколько миллисекунд, в зависимости от мощности вашей машины.

Прежде всего, оболочка печатает приглашение, предлагая пользователю ввести команду. Оболочка считывает команду ls -l из STDIN функции getline(), разбирая командную строку на аргументы, которые будут переданы выполняемой программе. Оболочка проверяет, является ли ls псевдонимом. Если это так, псевдоним заменяет ls своим значением. Если ls не является псевдонимом, оболочка проверяет, является ли слово (команда) встроенным. Затем оболочка ищет программный файл с именем ls, где все исполняемые файлы находятся в системе — в окружении оболочки (массив строк), в частности, в переменной $PATH. Переменная $PATH представляет собой список каталогов, которые оболочка ищет при каждом вводе команды. $PATH — это одна из переменных среды, которая анализируется с использованием «=» в качестве разделителя. Как только $PATH идентифицирован, все каталоги в $PATH токенизируются, далее анализируются с использованием «:» в качестве разделителя.

Бинарный исполняемый файл ls будет расположен [в одном из основных подкаталогов каталога '/usr'] в файле '/usr/bin/ls' — '/usr/bin' содержит большинство исполняемых файлов (т.е. программы для запуска).

«ls» — это имя программы или команды, встроенной в оболочку для запуска. «-l» — это специальные аргументы, называемые параметрами, которые помогают команде «ls» отображать список файлов в длинном формате, включая разрешения, владельца, временные метки и размеры файлов. Большинство опций начинаются с дефиса, а затем с буквы (сама опция).

Учитывая ls –l *.c

В команду добавлен новый аргумент «*.c». Знак «*» называется подстановочным знаком, и здесь мы можем просто сказать, что он означает все. «.c» — это расширение для файлов, содержащих программы, написанные на языке C — короткие файлы, оканчивающиеся на «.c». Таким образом, когда кто-то набирает эту команду, она указывает оболочке перечислить все файлы C в текущем каталоге, в формате длинного списка.