Приветствую всех самым категорическим
образом. Помнится, не раз и не два во "мнениях"
проскакивали сообщения типа "… и пишите
побольше о программинге под никсы!".
Танцуйте, господа, мы открываем рубрику под
названием [см. сабж]. Клятвенно заверяю, что
постараемся сделать ее более-менее
регулярной, хотя обещать ничего не могу, ибо
смотреть в будущее с уверенностью — еще не
значит быть уверенным в этом будущем ;-). И
перед тем, как начать, обращу ваше внимание
на две вещи.

Во-первых, я не буду объяснять каждую
строчку кода, тем паче, что программинг
будет ну на самом зачаточном уровне — нам
главное идею понять, а не полмиллиона
строчек кода наваять. Но, тем не менее, бреда
типа "вот эта бука есть ни что иное, как
ссылка на ту каку, которая, в свою очередь,
указатель на адрес той бяки" не будет
точно — учите Си, и ваши волосы будут мягкими
и шелковистыми.

Во-вторых, обращаюсь к тем, кто уже
навострил клаву писать всякую гадость во
"мнения" и обвинять автора в третьей
степени ламерства. Перцы! Я уверен, что
среди вас есть знающие люди, и рад этому.
Также я уверен, что есть и те, которые
посмеиваются над потугами авторов
втолковать что-то начинающим, и в худших
случаях эти "посмеивания" выливаются в
мнения типа "Ну ты ламо, такие вещи писать,
ваще все это сто лет назад узнали". И к
таким у меня вопрос: а не лучше ли, вместо
этого, сеть и самим написать материал в
колонку, раз вы так все хорошо знаете? Это
куда как достойнее испражнения в ослоумии,
и все будут только рады. Все, я все сказал.
Теперь — к делу. Те, кто не хочет изучать
умные скучные книжки об устройстве UNIX и о
программинге на Си, но любит посещать xakep.ru,
приготовьтесь нехило прогрузиться! 8-).

Начнем мы наш экскурс с осознания того, в
чем, собственно, состоит гибкость никсов по
сравнению с другими осями. Если кто не знает,
все в нем состоит из отдельных процессов,
взаимодействующих между собой.. То есть
выводишь ты текст на экран — это один
процесс, пишешь в файл — другой процесс,
запускаешь прогу — она, в свою очередь, есть
еще один процесс. Процесс, не побоюсь этого
слова, есть центральная фича юникса 8-). То
есть, это — отдельно выполняющаяся
программа, имеющая вполне фиксированный
доступ к ресурсам машины. Если у себя в
юнихе ты наберешь:

$ ps

то увидишь, сколько процессов выполняется
в текущий момент. В этом-то и есть основная
гибкость оси: в силу того, что отдельные
процессы взаимодействуют между собой,
вполне имеет право на жизнь, скажем, такая
строчка:

$ tar cvf — file1.jpg file2.jpg file3.jpg | gzip -5 >
mylittlepornoarchive.tar.gz

где ты сначала сжимаешь файлы tar’ом, затем
зипуешь их и создаешь архивное файло — и все
это за один прием, благодаря тому, что tar, gzip
и перенаправление в файл — это отдельные
взаимодействующие процессы. Будь уверен,
консольные гуру и не такой длины строчки
сочиняют…

Что еще нужно знать, прежде чем приступить
работать с процессами? Когда ты выводил их
список, ты, конечно, увидел у каждого некие
цифры под подписью PID. Это есть ни что иное,
как process identificator — логично, не правда ли,
чтобы каждый из тьмы процессов имел
собственный идентификатор, а то как же его
выцеплять из тысячи остальных? Также, в силу
того, что процессы порождаются и умирают
все время (посмотри, когда ты набирал $ ps [enter],
ты сделал ни что иное, как создал процесс (все
в никсе делают процессы, помнишь?) ps, который
занимается тем, что выводит список
процессов, включая и себя, конечно. Как
только он сделал все, что от него требуется —
список вывел — он умирает, дабы не занимать
процессорные ресурсы), так вот, в силу того,
что процессы рождаются и умирают постоянно,
каждый процесс имеет не только PID —
идентификатор себя, но и PPID — parent PID, т.е.
идентификатор своих "родителей", того
процесса, который его породил. В данном
случае, очевидно, процесс ps порожден
процессом tty — вводом с консоли.

Ну да это все пустое гонево, скажешь ты,
при чем же тут программинг? Отлично,
переходим к написанию проги, цель наша —
научиться управлять процессами, то есть
создавать их, передавать им управление,
заставлять их делать что-нибудь полезное,
ну и убивать их, естественно 8-). Думаешь, это
трудно? Ничуть. Все, что тебе потребуется
знать (при условии, что ты более-менее
сносно знаешь Си), это пара-тройка чисто
юниксовых функций.

Порождает процессы функция fork(). Синтаксис
у нее такой: возвращает ноль, если процесс
создан успешно, и -1 — если нет. Реализовать,
соответственно, можно по-разному. ИМХО,
самое очевидное — через функцию выбора switсh-case,
так как это более наглядно, чем строить
конструкции типа if (fork()=-1) then … else … :

    main()
{
switch (fork())
{
case 0 :

printf("\n Created pid %d with ppid %d \n", getpid(), getppid());

exit(0);
case -1 :

exit(1);
default :

printf(" Current pid is %d with ppid %d \n", getpid(), getppid());

exit(0);
}
}

Эта маленькая программка создает один
новый процесс. Функции getpid() и getppid() просто-напросто
выдают PID и PPID текущего процесса. Сюда я их
включил, чтобы ты убедился: порожденный
процесс имеет Parent PID, равный PID’у процесса
изначального, порождающего процесса (т.е.
программы). Что и требовалось доказать ;-). 
Сказали о порождении процессов, теперь
логично было бы рассказать об их убийстве.
Занимается этим зловещая функция kill (какое
оригинальное название 8-). Синтаксис ее
таков:

kill (pid_t pid_number, SIGKILL);

Первое — номер процесса (берется в программе,
как ей надобно, в соответствии с задачей,
или вводится ручками как переменная спец.
типа pid_t), второе — посылаемый ему сигнал.
Надо сказать, что функция kill, не смотря на
свое очевидное название,
многофункциональна, и SIGKILL — всего лишь один
из возможных передаваемых процессу
сигналов (в данном случае — это сигнал
процессу умереть 8-), их все мы тут
рассматривать не будем. Очевидно, кусок
кода в проге, отвечающий за убийство
указываемых тобою процессов, будет
примерно таков:

pid_t gpid;
printf("Input PID to kill\n");
scanf("%d",&gpid);
kill (gpid, SIGKILL);

Ты
вводишь ручками номер приговоренного
процесса, и он тихо умирает, будучи не в
силах сопротивляться функции
kill
;-).

Итак,
про рождение мы узнали, про убийство – тоже,
осталось собрать все воедино и наваять
прогу, которая бы создавала любое,
указанное тобой кол-во процессов, а затем
любой же из них (или сразу все вместе)
убивала.

Прога
получается наилементарнейшая, главную
функцию ее я реализовал опять-таки через
switch,
просто потому, что конструкция получается
очень понятная и стройная, легкая к чтению.

Заставляем функцию fork
возвращать PID
созданного процесса, это понадобится для
главной функции. Для того, чтобы создавать
не один процесс, а сколько душе угодно,
стряпаем массивчик, куда будем пихать
созданные fork’ом
PID’ы
процессов (вот для чего нужно требовать от fork
их возвращения), кол-во элементов массива,
разумеется, задаем сами – сколько их будет,
столько раз функцию fork
и вызовем, столько процессов породим.
Убийство реализуем как в виде возможности
прикончить отдельно взятый процесс (по его PID’у),
так и возможности  грохнуть
все сразу. Вот, вроде, и все, по сорцу
разберешься.

Процессы-то мы создаем, а
вот что они делают — непонятно. Позже ты
научишься управлять ими, заставляя
выполнять определенное действие. Ведь
работа с процессами — одна из самых мощных
сторон OS UNIX.

Исходники

Оставить мнение

Check Also

LUKS container vs Border Patrol Agent. Как уберечь свои данные, пересекая границу

Не секрет, что если ты собрался посетить такие страны как США или Великобританию то, прежд…