UNIX: разработка сетевых приложений
<i>Возвращает: 0 в случае успешного выполнения, положительное значение Exxx в случае ошибки</i>Эта функция обычно вызывается потоком при необходимости изменить собственный статус в следующем формате:
pthread_detach(pthread_self());Функция pthread_exit
Одним из способов завершения потока является вызов функции
.pthread_exit#include <pthread.h>void pthread_exit(void *<i>status</i>);<i>Ничего не возвращает вызвавшему потоку</i>Если поток не является отсоединенным, идентификатор потока и статус завершения сохраняются до того момента, пока какой-либо другой поток данного процесса не вызовет функцию
.pthread_joinУказатель
не должен указывать на объект, локальный по отношению к вызывающему потоку, так как этот объект будет уничтожен при завершении потока.statusСуществуют и другие способы завершения потока.
■ Функция, которая была вызвана потоком (третий аргумент функции
), может возвратить управление в вызывающий процесс. Поскольку, согласно своему объявлению, эта функция возвращает указательpthread_create, возвращаемое ею значение играет роль статуса завершения данного потока.void■ Если функция
данного процесса возвращает управление или любой поток вызывает функциюmain, процесс завершается вместе со всеми своими потоками.exit26.3. Использование потоков в функции str_cli
В качестве первого примера использования потоков мы перепишем нашу функцию
. В листинге 16.6 была представлена версия этой функции, в которой использовалась функцияstr_cli. Напомним, что были также представлены и некоторые другие версии этой функции: изначально в листинге 5.4 функция блокировалась в ожидании ответа и была, как мы показали, далека от оптимальной в случае пакетного ввода; в листинге 6.2 применяется блокируемый ввод-вывод и функцияfork; версии, показанные в листинге 16.1 и далее, используют неблокируемый ввод-вывод.selectНа рис. 26.1 показана структура очередной версии функции str_cli, на этот раз использующей потоки, а в листинге 26.1 [1] представлен код этой функции.
Рис. 26.1. Измененная функция str_cli, использующая потоки
Листинг 26.1. Функция str_cli, использующая потоки
//threads/strclithread.c1 #include "unpthread.h"2 void *copyto(void*);3 static int sockfd; /* глобальная переменная, доступная обоим потокам */4 static FILE *fp;5 void6 str_cli(FILE *fp_arg, int sockfd_arg)7 {8 char recvline[MAXLINE];9 pthread_t tid;10 sockfd = sockfd_arg; /* копирование аргументов во внешние переменные */11 fp = fp_arg;12 Pthread_create(&tid, NULL, copyto, NULL);13 while (Readline(sockfd, recvline. MAXLINE) > 0)14 Fputs(recvline, stdout);15 }16 void*17 copyto(void *arg)18 {19 char sendline[MAXLINE];20 while (Fgets(sendline, MAXLINE, fp) != NULL)21 Writen(sockfd, sendline, strlen(sendline));22 Shutdown(sockfd, SHUT_WR); /* признак конца файла в стандартномпотоке ввода, отправка сегмента FIN */23 return (NULL);24 /* завершение потока происходит, когда в стандартном потоке вводавстречается признак конца файла */25 }Заголовочный файл unpthread.hМы впервые встречаемся с заголовочным файлом1. Он включает наш обычный заголовочный файлunpthread.h, затем — заголовочный файл POSIXunp.h, и далее определяет прототипы наших потоковых функций-оберток для<pthread.h>(см. раздел 1.4), название каждой из которых начинается сpthread_XXX.Pthread_Сохранение аргументов во внешних переменныхДля потока, который мы собираемся создать, требуются значения двух аргументов функции10-11:str_cli— указатель на структуруfpдля входного файла, иFILE— сокет TCP, связанный с сервером. Для простоты мы храним эти два значения во внешних переменных. Альтернативой является запись этих двух значений в структуру, указатель на которую затем передается в качестве аргумента создаваемому потоку.sockfdСоздание нового потокаСоздается поток, и значение нового идентификатора потока сохраняется в12. Функция, выполняемая новым потоком, — этоtid. Никакие аргументы потоку не передаются.copytoГлавный цикл потока: копирование из сокета в стандартный поток выводаВ основном цикле вызываются функции13-14иreadline, которые осуществляют копирование из сокета в стандартный поток вывода.fputsЗавершениеКогда функция15возвращает управление, функция main завершается при помощи вызова функцииstr_cli(см. раздел 5.4). При этом завершаются все потоки данного процесса. В обычном сценарии второй поток уже должен завершиться в результате считывания признака конца файла из стандартного потока ввода. Но в случае, когда сервер преждевременно завершил свою работу (см. раздел 5.12), при вызове функцииexitзавершается также и второй поток, чего мы и добиваемся.exit
