Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб.практикумСП.doc
Скачиваний:
39
Добавлен:
31.03.2015
Размер:
5.99 Mб
Скачать

12.4. Системный вызов exit

Системный вызов exit служит для завершения процесса и имеет следующий формат: void exit (int status). Системный вызов exit закрывает все дескрипторы файла процесса, освобождает его код, данные и стек, а затем заканчивает процесс. Когда дочерний процесс завершается, он посылает своему родителю сигнал SIGCHLD и ждет его код статуса – status завершения для того, чтобы принять его. Используются только младшие восемь битов статуса. Процесс, который ожидает своего родителя, чтобы принять от него код возврата, называется зомби-процессом. Родитель принимает код завершения дочернего процесса, выполняя системный вызов wait. Ядро гарантирует, что все осиротевшие дети завершающегося процесса усыновляются процессом init путем установки их PPID в 1. Процесс init всегда принимает коды завершения своих порожденных процессов.

12.5. Системный вызов wait

Системный вызов wait заставляет процесс приостанавливаться, пока один из его дочерних процессов не закончит выполнение. Данный вызов имеет следующий формат: wait (int* status). Успешный вызов wait возвращает PID завершившегося порожденного процесса и помещает код статуса в status, который кодируется следующим образом:

  • если правый байт status – 0, левый байт содержит восемь битов значения, возвращаемого системным вызовом wait;

  • если правый байт отличен от 0, самые правые семь битов равны номеру сигнала, который заставил дочерний процесс завершить работу, и оставшийся бит самого правого байта установлен в 1, если порожденный процесс произвел дамп памяти;

Если процесс выполняет системный вызов wait и не имеет дочерних процессов, wait возвращается немедленно с -1. Если процесс выполняет wait и один или большее его порожденных процессов уже зомби, wait возвращается немедленно со статусом одного из зомби.

Пример. Ниже приведен фрагмент программы на языке Си, иллюстрирующий применение системных вызовов fork, wait и exit

main ()

{

int pid, status, died;

switch(pid = fork()) { /* порождаем новый процесс */

case -1: /* аварийное завершение */

printf(“Can’t fork\n”);

exit(-1);

case 0: /* процесс потомок */

printf(“I am the child\n”);

exit(3);

default: /* процесс предок ожидает окончания процесса потомка */

died =wait(&status);

}

printf(“Child was %d\n”, pid);

printf(“%d died\n”, died);

printf(“Exit value %d\n”, status>>8);

printf(“Exit status %d\n”, status & 0377);

exit(0);

}

12.6. Системный вызов exec

Системный вызов exec заменяет программу текущего процесса. Процесс может заменить свой текущий код, данные и стек с таковыми другого исполняемого файла, используя один из системных вызовов семейства exec. Когда процесс выполняет exec, его номера PID и PPID остаются теми же самыми – заменяется лишь код, выполняемый процессом. Приведем форматы семейства системных вызовов exec:

execl(name, arg0, arg1, …, argn,0)

char *name, *arg0, *arg1, …, *argn;

execv(name, argv)

char *name, *argv[];

execle(name, arg0, arg1, …, argn,0, envp)

char *name, *arg0, *arg1, …, *argn, *envp[];

execve(name, argv, envp)

char *name, *argv[],*envp[] ;

Здесь аргумент name имеет тип данных указатель на символы и специфицирует имя файла, содержащего исполняемый код программ, а аргументы arg0, arg1, …, argn, которые также имеют тип данных указатель на символы, специфицируют аргументы этой программы, передаваемые ей при вызове ее на выполнение.

Системный вызов execl используется, как правило, в том случае, когда вызываемая на выполнение программа имеет фиксированное число аргументов. При этом аргумент arg0 специфицирует имя файла, содержащего вызываемую на выполнение программу, а в качестве последнего аргумента обязательно должен быть символ 0 или NULL.Например, рассмотрим вызов на выполнение команды ls с помощью системного вызова execl: execl(“/bin/ls”, “ls”, “-l”, 0). В качестве аргумента name использовано абсолютное полное имя файла, содержащего команду ls, в противном случае поиск файла будет осуществляться только в текущем каталоге.

Системный вызов execv, наоборот, используется чаще всего в случае, когда число аргументов вызываемой на выполнение программы заранее не известно. При этом аргумент name системного вызова специфицирует абсолютное полное имя файла, содержащего исполняемый код программы, а аргумент argv, имеющий тип данных массив указателей на символы, специфицирует весь список аргументов вызываемой на выполнение программы. Последним элементом этого списка должна быть строка, содержащая только символ 0 или NULL. В качестве примера рассмотрим вызов на выполнение команды ls с помощью системного вызова execv:

char *pv[] = {

“cc”,

“-0”,

“fred”,

“fred.c”,

0

};

main()

{

execv(“/bin/cc”, pv);

}

Пример. Ниже приведен фрагмент программы на языке Си, иллюстрирующий использование системных вызовов fork, wait, exit и execl:

main ()

{

int pid, status;

switch(pid = fork()) { /* порождаем новый процесс */

case -1: /* аварийное завершение */

printf(“Can’t fork\n”);

exit(-1);

case 0: /* процесс потомок */

printf(“I am the child\n”);

execl(“/bin/echo”, “echo”, “Hello mike !”, 0);

/* запускаем программу echoHello mike !” */

exit(1);

break;

default: /* процесс предок */

wait(&status);

/* ожидаем завершения процесса потомка */

}

/* процесс отец выводит на экран код завершения и статус завершения процесса потомка */

printf(“Exit value %d\n”, status>>8);

printf(“Exit status %d\n”, status & 0377);

exit(0);

}