Читаем UNIX: разработка сетевых приложений полностью

61 void*

62 do_get_read(void *vptr)

63 {

64  int fd, n;

65  char line[MAXLINE];

66  struct file *fptr;


67  fptr = (struct file*)vptr;


68  fd = Tcp_connect(fptr-f_host, SERV);

69  fptr-f_fd = fd;

70  printf("do_get_read for %s, fd %d, thread %d\n",

71   fptr-f_name, fd, fptr-f_tid);

72  write_get_cmd(fptr);


73  /* Чтение ответа сервера */

74  for (;;) {

75   if ((n = Read(fd, line, MAXLINE)) == 0)

76    break; /* сервер закрывает соединение */

77   printf ("read %d bytes from %s\n", n, fptr-f_name);

78  }

79  printf("end-of-file on %s\n\", fptr-f_name);

80  Close(fd);

81  fptr-f_flags = F_DONE; /* сбрасываем F_READING */


82  return (fptr); /* завершение потока */

83 }

Создание сокета TCP, установление соединения

68-71 Создается сокет TCP, и с помощью функции tcp_connectустанавливается соединение. В данном случае используется обычный блокируемый сокет, поэтому поток будет блокирован при вызове функции connect, пока не будет установлено соединение.

Отправка запроса серверу

72 Функция write_get_cmdформирует команду HTTP GETи отсылает ее серверу. Мы не показываем эту функцию заново, так как единственным отличием от листинга 16.12 является то, что в версии, использующей потоки, не вызывается макрос FD_SETи не используется maxfd.

Чтение ответа сервера

73-82 Затем считывается ответ сервера. Когда соединение закрывается сервером, устанавливается флаг F_DONEи функция возвращает управление, завершая выполнение потока.

Мы также не показываем функцию home_page, так как она полностью повторяет версию, приведенную в листинге 16.10.

Мы вернемся к этому примеру, заменив функцию Solaris thr_joinна более переносимую функцию семейства Pthreads, но сначала нам необходимо обсудить взаимные исключения и условные переменные.

26.7. Взаимные исключения

Обратите внимание на то, что в листинге 26.8 при завершении выполнения очередного потока в главном цикле уменьшаются на единицу и nconn, и nlefttoread. Мы могли бы поместить оба эти оператора уменьшения в одну функцию do_get_read, что позволило бы каждому потоку уменьшать эти счетчики непосредственно перед тем, как выполнение потока завершается. Но это привело бы к возникновению трудноуловимой серьезной ошибки параллельного программирования.

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

1. Выполняется поток А, который загружает в регистр значение переменной nconn(равное 3).

2. Система переключается с выполнения потока А на выполнение потока В. Регистры потока А сохранены, регистры потока В восстановлены.

3. Поток В выполняет три действия, составляющие оператор декремента в языке С ( nconn--), сохраняя новое значение переменной nconn, равное 2.

4. Впоследствии в некоторый момент времени система переключается на выполнение потока А. Восстанавливаются регистры потока А, и он продолжает выполняться с того места, на котором остановился, а именно начиная со второго этапа из трех, составляющих оператор декремента. Значение регистра уменьшается с 3 до 2, и значение 2 записывается в переменную nconn.

Окончательный результат таков: значение nconnравно 2, в то время как оно должно быть равным 1. Это ошибка.

Перейти на страницу:

Похожие книги

1001 совет по обустройству компьютера
1001 совет по обустройству компьютера

В книге собраны и обобщены советы по решению различных проблем, которые рано или поздно возникают при эксплуатации как экономичных нетбуков, так и современных настольных моделей. Все приведенные рецепты опробованы на практике и разбиты по темам: аппаратные средства персональных компьютеров, компьютерные сети и подключение к Интернету, установка, настройка и ремонт ОС Windows, работа в Интернете, защита от вирусов. Рассмотрены не только готовые решения внезапно возникающих проблем, но и ответы на многие вопросы, которые возникают еще до покупки компьютера. Приведен необходимый минимум технических сведений, позволяющий принять осознанное решение.Компакт-диск прилагается только к печатному изданию книги.

Юрий Всеволодович Ревич

Программирование, программы, базы данных / Интернет / Компьютерное «железо» / ОС и Сети / Программное обеспечение / Книги по IT
Access 2002: Самоучитель
Access 2002: Самоучитель

В книге рассматривается широкий круг вопросов, связанных с использованием программной среды Access 2002, которая является составной частью пакета Office 2002 и предназначена для создания банка данных в самых различных предметных областях.Подробно описывается методика проектирования объектов базы данных (таблицы, формы, отчеты, страницы доступа к данным, запросы, модули).Детально обсуждаются вопросы создания интегрированной базы данных в единой среде Access 2002: формирование БД с нуля, конвертирование в программную среду баз данных, созданных в ином программном окружении – Clarion, FoxPro.Особое внимание уделяется формированию разнообразных запросов к интегрированной базе данных Access 2002 с использованием языков программирования SQL, VBA и макросов.Приводятся общие сведения о возможностях языка обмена данными между различными компьютерами и приложениями (XML). Описываются возможности использования гиперссылок, связывающих базу данных с другими программными продуктами. Объясняется, как можно работать с базой данных Access 2002 без установки ее на компьютер, используя технологию ODBC (Open Data Base Connectivity). В приложениях приводятся количественные параметры Access 2002 и связанная с этой СУБД терминология.Предлагаемая книга будет полезна специалистам, занимающимся практической разработкой банков данных и приложений на их основе, а также студентам вузов, изучающим информатику.

Павел Юрьевич Дубнов

Программирование, программы, базы данных / ОС и Сети / Книги по IT