Создание процессов и исполнение программ



Скачать 336,76 Kb.
страница5/7
Дата12.09.2017
Размер336,76 Kb.
1   2   3   4   5   6   7

Использование execvp(2) - Пример

Этот пример использует execvp(2). execvp(2) и execlp(2) осуществляют поиск загружаемого файла программы в соответствии с переменной среды PATH. Вспомните, что PATH - это список директорий, разделённых двоеточием, в которых система должна искать загружаемые файлы.

Файл: exec4.c

ИСПОЛЬЗОВАНИЕ execvp(2) - ПРИМЕР


1 #include

2 #include

3

4 main()


5 {

6 char *nargv[ ] = {

7 "newpgm", "parm1", "parm2", "parm3",

8 (char *) 0 };

9

10 printf("this is the original program\n");



11

12 execvp("newpgm", nargv);

13 /* execlp("newpgm", "newpgm", "parm1", "parm2",

14 "parm3", (char *) 0); */

15

16 perror("This line should never get printed\n");



17 }
$ exec4

this is the original program

My input parameters(argv) are:

0: 'newpgm'

1: 'parm1'

2: 'parm2'

3: 'parm3'
My environment variables are:

HOME=/uxm2/jrs

LOGNAME=jrs

MAIL=/var/mail/jrs

PATH=/usr/bin:/usr/lbin/:/uxm2/jrs/bin:.

TERM=5420

TZ=EST5EDT

      1. Использование fork(2) и exec(2) - Пример

Этот пример представляет программу, которая порождает три процесса, каждый из которых запускает программу echo(1), используя системный вызов execl(2). Обратите внимание, что за каждым вызовом execl(2) следует сообщение об ошибке и завершение процесса. Сообщение будет распечатано, только если вызов execl(2) завершится неудачей.

Важно проверять успешность системных вызовов семейства exec(2), иначе может начаться исполнение нескольких копий исходной программы. В этом примере, если все вызовы exec(2) будут неудачными, может возникнуть восемь копий исходной программы.

Если все вызовы execl(2) были успешными, после последнего fork(2) будет существовать четыре процесса. Порядок, в котором они будут исполняться, невозможно предсказать.

Эта программа демонстрируется так:

$ forkexec1

Parent program ending

this is message three

this is message two

this is message one

Файл: forkexec1.c

ИСПОЛЬЗОВАНИЕ fork(2) И exec(2) - ПРИМЕР


1 #include

2 #include

3 #include

4 #include

5

6 main()


7 {

8

9 if (fork() == 0) {



10 execl("/bin/echo", "echo", "this is",

11 "message one", (char *) 0);

12 perror("exec one failed");

13 exit(1);

14 }

15 if (fork() == 0) {



16 execl("/bin/echo", "echo", "this is",

17 "message two", (char *) 0);

18 perror("exec two failed");

19 exit(2);

20 }

21 if (fork() == 0) {



22 execl("/bin/echo", "echo", "this is",

23 "message three", (char *) 0);

24 perror("exec three failed");

25 exit(3);

26 }

27

28 printf("Parent program ending\n");



29 }
      1. Завершение процесса

Системный вызов exit(2) предназначен для завершения процесса. Он прекращает исполнение вашей программы. В качестве параметра exit(2) передаётся код завершения в диапазоне от 0 до 255. По соглашению, значение 0 означает, что программа завершилась нормально. Значения от 1 до 255 означают, что программа завершилась из-за какой-либо ошибки.

Полезно использовать для каждого типа ошибки свой код завершения. Код завершения может быть получен родительским процессом через системный вызов wait(2). Это будет обсуждаться далее. Код завершения команды, исполненной из shell, доступен как переменная shell ${?}. Это полезно при написании командных файлов, выполняющих ветвление в зависимости от кода завершения, возвращённого командой.

exit(2) осуществляет действия по очистке, такие как закрытие всех открытых файлов и исполнение деструкторов статических переменных C++. Системный вызов _exit(2) сокращает эти действия по очистке. Например, _exit(2) не очищает буфера стандартной библиотеки ввода-вывода.

Вызов _exit(2) необходимо использовать в аварийных ситуациях, например, когда вы подозреваете повреждение памяти вашего процесса и имеете основания предполагать, что сброс буферов стандартной библиотеки может привести к записи в файлы некорректных данных.

В языках C/C++, возврат управления из функции main оператором return эквивалентен вызову exit(2). В действительности, такой возврат приводит к вызову exit(2). В этом можно убедиться, просмотрев ассемблерные исходники стартового файла среды исполнения языка C (crt1.o) или пройдя соответствующий оператор в отладчике (отладчик необходимо переключить из режима показа исходного текста в режим показа деассемблированного кода).


      1. Сигналы


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

При ошибках программирования: деление на ноль (SIGFPE), ошибки защиты памяти (SIGSEGV), ошибки обращения к памяти (SIGBUS).

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

В ответ на различные события: разрыв терминальной сессии (SIGHUP), разрыв трубы или сокета (SIGPIPE), завершение операции асинхронного ввода-вывода (настраивается при формировании запроса на ввод-вывод), срабатывание будильника (SIGALRM).

Также сигналы могут программно посылаться одними процессами другим процессам при помощи системных вызовов kill(2) и sigsend(2).

Каждый тип сигнала идентифицируется номером. Стандарт POSIX описывает 32 различных сигнала (нумерация начинается с 1); в ОС Solaris предусмотрено 64 типа сигналов.

Большинство необработанных сигналов приводит к завершению процесса, получившего этот сигнал. Это считается аварийным завершением процесса и отличается от завершения процесса по exit(2) или _exit(2).

Некоторые сигналы, например, SIGTSTP, SIGTTIN, SIGTTOUT, приводят не к завершению процесса, а к его приостановке. Приостановленный процесс находится в специальном состоянии, которое отличается от ожидания в блокирующемся системном вызове или на примитиве синхронизации. Приостановленный процесс может быть продолжен сигналом SIGCONT. Приостановка процессов используется при реализации управления заданиями, которое рассматриваются в разделе «Терминальный ввод-вывод», и отладчиками, которые в нашем курсе не рассматриваются.




      1. Поделитесь с Вашими друзьями:
1   2   3   4   5   6   7


База данных защищена авторским правом ©grazit.ru 2017
обратиться к администрации

    Главная страница