3. Модифицируйте программу так,
чтобы управление второй нитью осуществлялось посредством сигнала SIGUSR1 из
первой нити. На пятой секунде работы приложения удалите вторую нить. Для этого
воспользуйтесь функцией pthread_kill(t2, SIGUSR1), где
(t2 - дескриптор второй нити).
4. Последняя модификация
предполагает создание собственного обработчика сигнала, содержащего уведомление
о начале его работы и возврат посредством функции pthread_exit(NULL). Сравните
результаты, полученные после запуска этой модификации программы с результатами
предыдущей.
3. Выполнение работы.
3.1. Порождение и запуск процессов.
3.1.1. Ознакомиться с выполнением системных вызовов fork(); execl(); wait(); exit(); sleep().
Pid_t fork (void)
Системный вызов fork() занимается созданием нового процесса. При этом порожденный процесс является точной копией родителя за несколькими исключениями: он имеет свой идентификатор (PID), в качестве родительского идентификатора он имеет идентификатор процесса, вызвавшего fork(), дочерний процесс имеет свою собственную копию окружения родительского процесса.
Fork() возвращает дочернему процессу – 0, а родительскому, т.е. тому, который вызвал его, идентификатор дочернего процесса.
Int execl (const char * path, const char * arg0, …, const char * argN, NULL)
Для загрузки новой программы процесс должен выполнить системный вызов execl(). При этом новый процесс не порождается, а исполняемый код процесса полностью замещается кодом запускаемой программы. Окружение новой программы во многом сохраняется, в частности сохраняются значения переменных окружения, назначения стандартных потоков ввода/вывода и т.п.
pid_t wait (int *stat_loc)
Операционная система предоставляет процессу ряд функций, позволяющих ему контролировать выполнение потомков. Одна из таких функций – wait(). Она позволяет приостановить выполнение процесса, пока кто-либо из его непосредственных потомков не прекратит существование. Если дочерний процесс находится в стадии «зомби», то вызов wait() немедленно возвратит состояние уже завершившегося дочернего процесса в переменной stat_loc. Возвращаемое значение данного системного вызова – идентификатор завершающегося дочернего процесса.
Void exit (int status)
Системный вызов exit() приводит к завершению выполнения вызвавшей его задачи. Он ничего не возвращает, а аргумент status, передаваемый этой функции, возвращается родительскому процессу и представляет собой код возврата программы (0 – успех, другая величина - неуспех).
Unsigned int sleep (unsigned int seconds)
Системный вызов sleep() приостанавливает выполнение процесса на время, указанное в аргументе seconds. Возвращаемое значение 0, если интервал времени истек, или количество секунд, которые оставались до завершения интервала времени, если процесс был «разбужен».
3.1.2. Разработать программы родителя и потомка father.c и son.c. Скомпилировать программы, используя команду вида:
gcc -o name.out name.c.
Текст father.c.
#include <stdio.h>
main ()
{
int pid, ppid,status;
pid=getpid();
ppid=getppid();
printf ("\n\n FATHER PARAM: pid=%i ppid=%i \n", pid, ppid);
if (fork()==0)
execl("son.out","son.out", NULL);
system ("ps -la");
wait(&status);
}
Текст son.c.
#include <stdio.h>
main()
{
int pid, ppid;
pid=getpid();
ppid=getppid();
printf ("\n SON PARAM: pid=%i ppid=%i\n", pid, ppid);
sleep(15);
}
Запуск father.out.
$ ./father.out
FATHER PARAM: pid=913453 ppid=499756
SON PARAM: pid=917550 ppid=913453
Уважаемый посетитель!
Чтобы распечатать файл, скачайте его (в формате Word).
Ссылка на скачивание - внизу страницы.