Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лаб_процессы.doc
Скачиваний:
1
Добавлен:
27.11.2019
Размер:
225.28 Кб
Скачать

1.4 Ожидание процесса wait().

Существует системный вызов wait(), который блокирует родительский процесс до тех пор, пока не завершится один из его потомков. Этот системный вызов объявлен в заголовочном файле wait.h следующим образом:

pid_t wait(int * EXIT_STATUS) ;

Системный вызов wait() возвращает идентификатор завершившегося потомка. Указатель EXIT_STATUS содержит статус завершившегося потомка.

Статус завершившегося потомка – это целое число, содержащее код возврата некоторую другую информацию о том, как завершился процесс. Для извлечения этой информации существуют специальные макросы:

  • WIFEXITED() - возвращает ненулевое значение, если потомок завершился посредством возврата из функции main() или через вызов exit().

  • WEXITSTATUS() – возвращает код возврата завершившегося процесса. Этот макрос вызывается в том случае, если WIFEXITED() вернул ненулевое значение.

  • WIFSIGNALED() – возвращает ненулевое значение, если процесс был завершен посредством получения сигнала.

  • WTERMSIG(), WCOREDUMP(), WIFSTOPPED(), WSTOPSIG() и WCONTINUED() – относятся к сигналам.

Листинг 1.6 wait.c

#include <sys/types.h>

#include <unistd.h>

#include <stdio.h>

#include <errno.h>

#include<wait.h>

extern char ** environ;

int main()

{

pid_t status, childpid;

int exit_status;

char *calc_args[] = {"+","5","10",NULL};

status = fork();

if (status == -1)

{

fprintf(stderr,"fork error\n");

return 1;

}

/*Child*/

if (status == 0){

execve("./calc",calc_args,environ);

fprintf(stderr,"execve error\n");

return 1;

}

/*Parent*/

childpid = wait(&exit_status);

if (WIFEXITED(exit_status))

{

printf("Process with PID = %d\n has exited with code = %d\n",childpid, WEXITSTATUS(exit_status));

}

return 0;

}

1.5 Межпроцессорное взаимодействие, каналы( pipe() ).

Каналы осуществляют в Linux родственное локальное межпроцессное взаимодействие. Интерфейс канала представляет собой два связанных файловых дескриптора, один из которых предназначен для записи данных, другой – для чтения. Возможность родственного межпроцессного взаимодействия через канал обусловлена тем, что дочерние процессы наследуют от родителей открытые файловые дескрипторы.

Для создания канала служит системный вызов pipe(), объявленный в заголовочном файле unistd.h следующим образом:

int pipe(int PFDS[2]);

При успешном завершении системного вызова pipe() в текущем процессе появляется канал, запись в который осуществляется через дескриптор PFSD[1], а чтение – через PFSD[0]. При удачном завершении pipe() возвращает 0. В случае ошибки возвращается -1.

Данные, передаваемые через канал, практически не нуждаются в разделении доступа. Канал автоматически блокирует читающий или пишущий процесс, когда это необходимо. Если читающий процесс запрашивает больше данных, чем есть в настоящий момент в канале, то процесс блокируется до тех пор, пока в канале не появятся новые данные.

Закрытие концов канала осуществляется при помощи системного вызова close. Следует отметить, что снять блокировку с читающего процесса можно, закрыв входной конец канала. И наоборот: если пишущий процесс заблокирован операцией write(), например, то закрытие читающего конца канала снимает блокировку. Нужно помнить, что закрытие дескриптора происходит только тогда, когда все процессы, разделяющие этот дескриптор, вызовут close().

Листинг 1.7 pipe-parent.c

#include<stdio.h>

#include<unistd.h>

#include<sys/wait.h>

#define STR_SIZE 32

int main(void)

{

int pf[2];

int pid1,pid2;

char spf[2][STR_SIZE];

if (pipe(pf) == -1)

{

fprintf(stderr,"pipe() error\n");

return 1;

}

sprintf(spf[0],"%d",pf[0]);

sprintf(spf[1],"%d",pf[1]);

if ((pid1 = fork()) == 0 )

{

close(pf[0]);

execl("./pipe1","pipe1",spf[1],NULL);

fprintf(stderr,"exec() error\n");

return 1;

}

if ((pid2 = fork()) == 0 )

{

close(pf[1]);

execl("./pipe2","pipe2",spf[0],NULL);

fprintf(stderr,"exec() error\n");

return 1;

}

waitpid(pid1,NULL,0);

close(pf[0]);

close(pf[1]);

waitpid(pid2,NULL,0);

return 0;

}

Листинг 1.8 pipe1.c

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

#define PP_MESSAGE "Hello World\n"

#define WAIT_SECS 5

int main(int argc, char **argv)

{

int i, fd;

if(argc<2)

{

fprintf(stderr,"Error: Too few arguments\n");

return 1;

}

fd = atoi(argv[1]);

fprintf(stderr,"Wait please\n");

for (i = 0; i< WAIT_SECS; i++,sleep(1))

fprintf(stderr, ".");

fprintf(stderr,"\n");

if (write(fd, PP_MESSAGE, strlen(PP_MESSAGE)) == -1 )

{

fprintf(stderr,"write() error\n");

return 1;

}

close(fd);

return 0;

}

Листинг 1.9 pipe2.c

#include<stdio.h>

#include<stdlib.h>

#include<string.h>

#include<unistd.h>

int main(int argc, char **argv)

{

int fd;

char ch;

if(argc<2)

{

fprintf(stderr,"Error: Too few arguments\n");

return 1;

}

fd = atoi(argv[1]);

while(read(fd,&ch,1) > 0)

write(1,&ch,1);

close(fd);

return 0;

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]