Главная » Программирование для UNIX » Пример: zap

0

Программа  zap,  выборочно  уничтожающая   процессы, также  была  представлена в главе 5 в виде  командного файла. Основным недостатком той версии является скорость: программа создает так  много  процессов, что выполнение становится очень медленным, что нежелательно, особенно  для  программы, убивающей ошибочные процессы. Пере писанная на Си, zap будет работать быстрее. Не будем делать всю работу:  по-прежнему используем ps для  поиска информации о процессе. Это гораздо легче, чем получать информацию из ядра, к тому же такое решение переносимо. Программа  zap открывает канал, в котором со стороны ввода находится ps, и считывает данные оттуда, а не из файла. Функция popen(3) аналогична fopen, только первым аргументом является  не имя файла, а команда. Существует и функция pclose, которая не используется в данном примере.

/*  zap:  интерактивный  убийца процессов */

#include <stdio.h>

#include <signal.h>

char        *progname;    /*  имя программы  для сообщения  об ошибке  */ char        *ps  = "ps  –ag";  /*  зависит  от системы  */

main(argc,  argv) int  argc;

char  *argv[];

{

FILE  *fin,  *popen(); char  buf[BUFSIZ];

int pid;

progname = argv[0];

if ((fin  = popen(ps, "r"))  == NULL)  {

fprintf(stderr, "%s: can’t  run  %s\n",  progname, ps); exit(1);

}

fgets(buf, sizeof buf,  fin);     /*  получить заголовочную  строку */ fprintf(stderr, "%s",  buf);

while  (fgets(buf,  sizeof buf,  fin) !=  NULL)

if (argc == 1 ||  strindex(buf,  argv[1]) >= 0)  { buf[strlen(buf)–1]  =  ‘\0′; /*  suppress  \n  */ fprintf(stderr,  "%s?  ", buf);

if  (ttyin()  ==  ‘y’)  { sscanf(buf,  "%d",  &pid); kill(pid,  SIGKILL);

}

}

exit(0);

}

Программа была  написана с использованием ps  –ag (параметр зависит от конкретной системы),1  но до тех пор пока  вы не станете привилегированным пользователем, вы сможете уничтожать только свои  собственные процессы.

При  первом вызове fgets получает от ps заголовочную строку (попро буйте   понять, что  произойдет,  если   попытаться  уничтожить  «процесс», соответствующий этой заголовочной строке – это полезное упражнение).

Функция sscanf принадлежит к семейству  scanf(3), занимающемуся преобразованием формата ввода. Она конвертирует не файл, а строку. Системный вызов kill посылает указанный сигнал процессу; при этом сигнал SIGKILL, определенный в <signal.h>, не может быть  перехвачен или  проигнорирован. Может быть, вы  помните (об этом  говорилось в главе 5), что  численное значение отправленного  сигнала равно  9,  но лучше использовать символьные константы, а не разбрасывать по программе магические числа.

Если   аргументы не  заданы,  команда  zap  предоставляет для выбора каждую строку вывода ps. Если  же аргумент указан, то zap предлагает только  соответствующие  ему   строки  вывода  ps.  Функция  strin– dex(s1,s2)  проверяет,  соответствует ли   аргумент  какой-либо  части строки вывода ps, используя strncmp (см.  табл. 6.2). Функция strindex

1        Параметр –a требует отображения процессов всех пользователей, а не толь ко тех,  которые принадлежат пользователю, запустившему ps. В System V ps  –a не выводит процессы, являющиеся лидерами группы процессов, для  включения их в выводимый список необходим параметр –g. В ОС ветви BSD действие параметра –g не  определено.  Например, во FreeBSD v. 4.4  ps не имеет параметра –g, но его указание при запуске ps сообщений об ошибке не вызывает. – Примеч. науч. ред.

возвращает позицию в s1, в которой встретилась s2, или  –1, если  соответствие не обнаружено.

strindex(s, t)   /*  возвращает индекс t в s  и –1,  если не найдено */ char  *s,  *t;

{

int i, n;

n = strlen(t);

for  (i = 0;  s[i] !=  ‘\0′; i++)

if  (strncmp(s+i,  t,  n)  ==  0) return  i;

return –1;

}

Список наиболее часто  применяемых функций из стандартной библи отеки ввода-вывода приведен в табл. 6.4.

Таблица 6.4. Полезные стандартные функции ввода5вывода

Функция

Действие

fp=fopen(s,mode)

c=getc(fp) putc(c,fp) ungetc(c,fp)

scanf(fmt,a1,…)

fscanf(fp,…) sscanf(s,…) printf(fmt,a1,…) fprintf(fp,…) sprintf(s,…) fgets(s,n,fp)

fputs(s,fp) fflush(fp) fclose(fp) fp=popen(s,mode) pclose(fp) system(s)

открыть файл s; режимы r, w, a для чтения, записи и добавления (в случае ошибки возвращает NULL)

извлечь символ; getchar() – это getc(stdin)

вставить символ; putchar() – это putc(c,  stdout)

вернуть символ обратно в файл ввода  fp, за один раз не более одного символа

читать символы из stdin в a1, … в соответствии с fmt. Каждый ai должен быть указателем. Возвращает EOF или количество преобразованных полей

читать из файла fp

читать из строки s

форматировать a1, … в соответствии с fmt, выводить в stdout

выводить … в файл fp

выводить … в строку s

прочитать не более чем n символов из fp в s. В конце файла возвращает NULL

выводить строку s в файл fp

сбросить буферизованный вывод для файла fp

закрыть файл fp

открыть канал для команды s. См. fopen

закрыть канал fp

запустить команду s и ждать завершения

Упражнение 6.11.  Измените zap так, чтобы можно было  задавать любое количество аргументов. Предложенная версия zap предлагает для выбора строку, соответствующую самой  себе. Правильно ли это? Если  нет,  измените программу. Подсказка: getpid(2). ~

Упражнение 6.12.  Напишите функцию fgrep(1), основываясь на strin– dex. Сравните время исполнения при  сложном поиске, например для 10 слов в документе. Почему fgrep работает быстрее? ~

Источник: Керниган Б., Пайк Р., UNIX. Программное окружение. – Пер. с англ. – СПб: Символ-Плюс, 2003. – 416 с., ил.

По теме:

  • Комментарии