Читать интересную книгу UNIX: взаимодействие процессов - Уильям Стивенс

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 117 118 119 120 121 122 123 124 125 ... 128

Функции Posix для работы с потоками обычно возвращают 0 в случае успешного завершения работы и ненулевое значение в случае ошибки. В отличие от большинства системных функций, возвращающих –1 в случае ошибки и устанавливающих значение errno равным коду ошибки, функции Pthread возвращают положительный код ошибки. Например, если pthread_create не сможет создать новый поток из-за превышения системного oгрaничeния на потоки, эта функция вернет значение EAGAIN. Функции Pthread не устанавливают значение переменной errno. Несоответствий при их вызове не возникает, поскольку ни один из кодов ошибок не имеет нулевого значения (<sys/errno.h>).

Функция pthread_join

Мы можем ожидать завершения какого-либо процесса, вызвав pthread_join. Сравнивая потоки с процессами Unix, можно сказать, что pthread_create аналогична fork, a pthread_join — waitpid:

#include <pthread.h>

int pthread_join(pthread_t tid, void **status);

/* Возвращает 0 в случае успешного завершения, положительное значение Еххх – в случае ошибки */

Мы должны указать идентификатор потока, завершения которого ожидаем. К сожалению, невозможно задать режим ожидания завершения нескольких потоков (аналога waitpid с идентификатором процесса –1 нет).

Если указатель status ненулевой, возвращаемое потоком значение (указатель на объект) сохраняется в ячейке памяти, на которую указывает status.

Функция pthread_self

У каждого потока имеется свой идентификатор, уникальный в пределах данного процесса. Идентификатор возвращается pthread_create и используется при вызове pthread_join. Поток может узнать свой собственный идентификатор вызовом pthread_self:

#include <pthread.h>

pthread_t pthread_self(void);

/* Возвращает идентификатор вызвавшего потока */

Вызов pthread_self является аналогом getpid для процессов Unix.

Функция pthread_detach

Поток может являться как присоединяемым (по умолчанию), так и отсоединенным. При завершении присоединяемого потока его идентификатор и статус завершения сохраняются до тех пор, пока какой-либо другой поток данного процесса не вызовет pthread_join. Отсоединенный поток функционирует аналогично процессу-демону. После его завершения все ресурсы освобождаются. Никакой другой поток не может ожидать его завершения. Если имеется необходимость ожидания одним потоком завершения другого, лучше оставить последний присоединяемым.

Функция pthread_detach делает данный поток отсоединенным:

#include <pthread.h>

int pthread_detach(pthread_t tid);

/* Возвращает 0 в случае успешного завершения, положительное значение Еххх в случае ошибки */

Эта функция вызывается потоком при необходимости изменить собственный статус в форме

pthread_detach(pthread_self());

Функция pthread_exit

Одним из способов завершения потока является вызов pthread_exit:

#include <pthread.h>

void pthread_exit(void *status);

/* ничего не возвращает вызвавшему потоку */

Если поток не является отсоединенным, его идентификатор и статус завершения сохраняются для возвращения другому потоку, который может вызвать pthread_join.

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

Поток может быть завершен двумя другими способами:

■ начальная функция потока (третий аргумент pthread_create) может вызвать return. Поскольку эта функция должна объявляться как возвращающая указатель на тип void, это возвращаемое значение становится статусом завершения потока;

■ функция main процесса может завершить работу или один из потоков может вызвать exit или _exit. При этом процесс завершает работу немедленно, вместе со всеми своими потоками.

ПРИЛОЖЕНИЕ В

Вспомогательные исходные коды

В.1. Заголовочный файл unpipc.h

Почти все программы книги подключают заголовочный файл unpipc.h, приведенный в листинге В.1.[1] Он подключает все стандартные системные заголовки, нужные большинству пpoгрaмм для работы с сетью, вместе с некоторыми общими системными заголовками. Он также определяет константы типа MAXLINE и прототипы функций ANSI С для функций, определенных в тексте (типа px_ipc_name), и для всех используемых в книге оберток. Мы не приводим эти прототипы.

Листинг В.1. Заголовочный файл unpipc.h

//lib/unpipc.h

1   /* Наш заголовочный файл. */

2   #ifndef __unpipc_h

3   #define __unpipc_h

4   #include "../config.h" /* параметры конфигурации ОС */

5   /* "../config.h" создается сценарием configure */

6   /* изменяя список директив #include, нужно изменять файлы

7    ../aclocal.m4 и ../configure.in. чтобы работал сценарий configure */

8   #include <sys/types.h> /* базовые типы данных */

9   #include <sys/time.h> /* структура timeval{} для select() */

10  #include <time.h> /* timespec{} для pselect() */

11  #include <errno.h>

12  #include <fcntl.h> /* отключение блокировки */

13  #include <limits.h> /* PIPE_BUF */

14  #include <signal.h>

15  #include <stdio.h>

16  #include <stdlib.h>

17  #include <string.h>

18  #include <sys/stat.h> /* константы режима доступа к файлу S_xxx */

19  #include <unistd.h>

20  #include <sys/wait.h>

21  #ifdef HAVE_MQUEUE_H

22  #include <mqueue.h> /* очереди сообщений Posix */

23  #endif

24  #ifdef HAVE_SEMAPHORE_H

25  #include <semaphore.h> /* семафоры Posix */

26  #ifndef SEM_FAILED

27  #define SEM_FAILED ((sem_t *)(-1))

28  #endif

29  #endif

30  #ifdef HAVE_SYS_MMAN_H

31  #include <sys/mman.h> /* разделяемая память Posix */

32  #endif

33  #ifndef MAP_FAILED

34  #define MAP_FAILED ((void *)(-1))

35  #endif

36  #ifdef HAVE_SYS_IPC_H

37  #include <sys/ipc.h> /* System V IPC */

38  #endif

39  #ifdef HAVE_SYS_MSG_H

40  #include <sys/msg.h> /* очереди сообщений System V */

41  #endif

42  #ifdef HAVE_SYS_SEM_H

43  #ifdef __bsdi__

44  #undef HAVE_SYS_SEM_H /* тонкий момент: прототип semctl() в BSDI's содержит ошибки*/

45  #else

46  #include <sys/sem.h> /* семафоры System V */

47  #endif

48  #ifndef HAVE_SEMUN_UNION /* $$.It semun$$ */

49  union semun { /* определение объединения для semctl() */

50   int val;

51   struct semid_ds *buf;

52   unsigned short *array;

53  };

54  #endif

55  #endif /* HAVE_SYS_SEM_H */

56  #ifdef HAVE_SYS_SHM_H

57  #include <sys/shm.h> /* разделяемая память System V */

58  #endif

59  #ifdef HAVE_SYS_SELECT_H

60  #include <sys/select.h> /* для удобства */

61  #endif

62  #ifdef HAVE_POLL_H

63  #include <poll.h> /* для удобства */

64  #endif

65  #ifdef HAVE_STROPTS_H

66  #include <stropts.h> /* для удобства */

67  #endif

68  #ifdef HAVE_STRINGS_H

69  #include <strings.h> /* для удобства */

70  #endif

71  /* Следующие три заголовочных файла нужны для ioctl файлов и сокетов:

72   * <sys/ioctl.h>, <sys/filio.h>, и <sys/sockio.h>.

73   */

74  #ifdef HAVE_SYS_IOCTL_H

75  #include <sys/ioctl.h>

76  #endif

77  #ifdef HAVE_SYS_FILIO_H

78  #include <sys/filio.h>

79  #endif

80  #ifdef HAVE_PTHREAD_H

81  #include <pthread.h>

82  #endif

83  #ifdef HAVE_DOOR_H

84  #include <door.h> /* интерфейс дверей Solaris */

85  #endif

86  #ifdef HAVE_RPC_RPC_H

87  #ifdef _PSX4_NSPACE_H_TS /* баги Digital Unix 4.0b */

88  #undef SUCCESS

89  #endif

90  #include <rpc/rpc.h> /* Sun RPC */

91  #endif

92  /* Определяем bzero() как макрос, если его нет в стандартной библиотеке С */

93  #ifndef HAVE_BZERO

94  #define bzero(ptr,n) memset(ptr, 0, n)

95  #endif

96  /* Posix.1g требует, чтобы INFTIM определялось в <poll.h>. но во многих системах эта

97     константа все еще определяется в <sys/stropts.h>. Нам не нужно подключать все

98     функции для работы с потоками, поэтому мы определяем INFTM здесь. Это стандартное

99     значение, но нет гарантий, что оно равно –1 */

100 #ifndef INFTIM

101 #define INFTIM (-1) /* неограниченное время опроса */

102 #ifdef HAVE_POLL_H

103 #define INFTIM_UNPH /* чтобы из файла unpxti.h узнать, что константа определена */

104 #endif

105 #endif

106 /* Прочие константы */

107 #ifndef РАТН_МАХ /* должна быть в <limits.h> */

108 #define PATH_MAX 1024 /* максимальное количество символов в полном имени файла */

1 ... 117 118 119 120 121 122 123 124 125 ... 128
На этом сайте Вы можете читать книги онлайн бесплатно русская версия UNIX: взаимодействие процессов - Уильям Стивенс.

Оставить комментарий