Изучение основных принципов управления процессами и нитями в ОС LINUX, страница 2

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