Здравствуйте, уважаемые подписчики. Извиняюсь за задержку с выпуском рассылки. В связи с моей чрезмерной загруженностью сайт не обновлялся, однако в ближайшее время на нем произойдут грандиозные перемены.
В этом выпуске мы начинаем изучать огромную тему "Многозадачность в Linux", которая протянется на несколько выпусков.
Позвольте выразить благодарность всем тем, кто помогает мне формировать проект LinuxProgrammer. Я очень ценю вашу поддержку.
2. Программирование в Linux
2.1. Разбор домашнего задания
Узнайте (а если знаете, то повторите), что такое ссылка в файловой системе. Узнайте также, чем символическая ссылка отличается от жесткой. Домашнее задание 6.1
Разбор домашнего задания
Опишу кратко. Итак, ссылка - это файл, указывающий на другой файл. Символическая ссылка - это простой указатель на файл. Если, например, удалить файл, на который указывает символическая ссылка, то такая ссылка станет "пустой", т.е. указывающей на несуществующий файл.
Жесткая ссылка - это еще одно имя для одного и того же файла. При создании жесткой ссылки копирования не происходит, просто один и тот же файл становится доступным по нескольким именам (жестким ссылкам). Чтобы реально удалить файл, на который указывает жесткая ссылка, нужно удалить все жесткие ссылки на этот файл. Создавая файл мы одновременно создаем для него жесткую ссылку (его имя).
Создавать ссылки позволяет команда ln
Очень скоро будет рассмотрена тема создания статических библиотек. Здесь мы вспомним и динамические библиотеки. Тогда нам и понадобятся ссылки, чтобы максимально облегчить контроль версий.
2.2. Введение в многозадачность Linux
Операционная система Linux является многозадачной. За многозадачность отвечает ядро. Что же представляет собой многозадачность? Мы привыкли под этим термином понимать концепцию одновременного выполнения нескольких программ. Однако такое понимание не является корректным в плане программирования. Во-первых - реально многозадачности не существует. Во-вторых - есть понятие процесс и есть понятие программа, которые нельзя отождествлять.
Итак, многозадачности не существует. Действительно, любой компьютер - это императивная машина, т.е. машина, основанная на последовательном анализе состояния вычислителя и изменении состояния этого вычислителя. Число комбинаций всевозможных состояний в такой системе конечно. Многозадачность, реализованная в операционных системах - это иллюзия, весьма удобная пользователю. Любая многозадачность - это абстракция императивности. То есть, мы думаем, что два процесса выполняются одновременно, а на самом деле они просто поочередно используют процессор для выполнения своих команд. За очередностью использования процессора следит хитрое ядро, которое и создает иллюзию многозадачности.
Чем же программа отличается от процесса? Программа - это нечто, готовое к выполнению, а процесс - это выполняющийся экземпляр программы. Почему экземпляр? Все дело в том, что одну и ту же программу можно запустить, например, два раза. Таким образом получится два процесса, хотя программа одна.
К каждому процессу в Linux привязываются два 16-разрядных числа - идентификатор процесса и идентификатор родителя. Первое число обычно обозначают PID (Process IDentifier), а второе - PPID (Parent Process IDentifier). Каждый процесс имеет свой уникальный PID. А что же такое PPID? Дело в том, что все процессы в Linux имеют иерархическую структуру. То есть одни процессы рождают другие процессы. Пусть процесс 1 породил процесс 2. В таком случае процесс 1 называют родителем или родительским процессом, а процесс 2 - потомком или дочерним процессом. Процесс 2, являющийся дочерним, может стать одновременно и родителем. И есть только один процесс, возвышающийся над всеми процессами и не имеющий родителя - это процесс init с идетрификатором 1 (PID=1). Это процесс запускается при загрузке системы. Программой
соответствующей этому процессу является демон init, запускаемый ядром.
Перед тем, как продолжить изучение многозадачности, выполните следующее домашнее задание.
Узнайте, что делают команды ps, kill, bg и fg. Изучите основные опции и аргументы команд ps и kill.
Домашнее задание 7.1
А теперь разберем простейший пример программы, которая порождает процесс. Здесь для порождения процесса используется функция system() из стандартной библиотеки языка C. Эта функция просто передает команду командному интерпретатору. Команда передается в функцию в виде строки, например "cp file1 file2". На выходе функции будет код возврата выполненной команды.
Кстати, узнать код возврата последней выполненной команды можно следующим образом:
|$ echo $?
Вообще говоря, функция system() не очень удачная, и не подходит для использования в программах, написанных для распространения. Рассмотрев эту функцию сейчас, мы больше не будем ее касаться, и станем порождать процессы более надежным способом. В следующем выпуске рассылки я расскажу, почему функция system() является столь неудачной. Однако будучи кандидатами в профессиональные Linux-программисты, вы должны знать, что есть такая функция.
Рассмотрим следующий пример. Пусть имеется файл с именем file1 и файл с именем file2. Требуется объединить текст в этих файлах и записать результат в файл с именем file3. Используя средства командного интерпретатора bash мы реализуем эту задумку.
Создайте файлы file1 и file2 и введите в них какой-нибудь текст. Например, введите в file1 текст "I love ", а в file2 - текст "Linux!". Теперь создадим файл psystem.cpp и напишем нашу первую программу, порождающую процесс.
/* psystem.cpp - source file */
#include <cstdlib>
using namespace std;
int main ()
{
int rcode;
rcode = system ("cat file1 > file3");
if (!rcode) {
rcode = system ("cat file2 >> file3");
} else {
return rcode;
}
return rcode;
}Листинг 7.1
Теперь откомпилируем и соберем программу:
|$ g++ -o psystem psystem.cpp
Если есть желание, можете использовать Makefile.
Уточните, чем командный интерпретатор отличается от командной оболочки.
Домашнее задание 7.2