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

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

Во-вторых, обращаюсь к тем, кто уже
навострил клаву писать всякую гадость во
"мнения" и обвинять автора в третьей
степени ламерства. Перцы! Я уверен, что
среди вас есть знающие люди, и рад этому.
Также я уверен, что есть и те, которые
посмеиваются над потугами авторов
втолковать что-то начинающим, и в худших
случаях эти "посмеивания" выливаются в
мнения типа "Ну ты ламо, такие вещи писать,
ваще все это сто лет назад узнали". И к
таким у меня вопрос: а не лучше ли, вместо
этого, сеть и самим написать материал в
колонку, раз вы так все хорошо знаете? Это
куда как достойнее испражнения в ослоумии,
и все будут только рады. Все, я все сказал.
Теперь - к делу. Те, кто не хочет изучать
умные скучные книжки об устройстве 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.

Исходники

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Межтекстовые Отзывы
    Посмотреть все комментарии