1 / 32

НИТИ И СТАНДАРТНЫЕ БИБЛИОТЕКИ Unix

НИТИ И СТАНДАРТНЫЕ БИБЛИОТЕКИ Unix. Программирование с использованием POSIX thread library. По завершении этого раздела вы сможете:. использовать стандартные библиотеки или их аналоги в многопоточных программах

haroun
Download Presentation

НИТИ И СТАНДАРТНЫЕ БИБЛИОТЕКИ Unix

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. НИТИ И СТАНДАРТНЫЕ БИБЛИОТЕКИ Unix Программирование с использованием POSIX thread library

  2. По завершении этого раздела вы сможете: • использовать стандартные библиотеки или их аналоги в многопоточных программах • находить в документации информацию о том, является ли данная функция или группа функций thread-safe • использовать сигналы и fork в многопоточных программах

  3. fork(2) в многопоточной среде • нити создаются в рамках процесса • fork(2) дублирует все состояние процесса • что происходит с нитями? • fork1 (дублируется только та нить, которая позвала fork) • forkall (дублируются все нити процесса) • в стандарте POSIX и Solaris 10fork(2)≡fork1 • в старых версиях Solaris, fork(2)≡forkall. • в других реализациях POSIX threads эквивалента forkall может вообще не быть

  4. fork1(2) • дублируется только нить, вызвавшая fork1(2) • сохраняются все блокировки, установленные остальными нитями (в том числе блокировки, скрытые внутри библиотечных функций) • вызов таких функций может привести к мертвой блокировке (будете ждать нити, которой не существует)

  5. pthread_atfork(3C) ИСПОЛЬЗОВАНИЕ #include <sys/types.h> #include <unistd.h> int pthread_atfork(void (*prepare) (void),void (*parent)(void), void (*child) (void)); ОПИСАНИЕ Регистрирует обработчики, вызываемые перед fork1 (prepare) и после него (parent, child). Порядок вызовов atfork имеет значение. Обработчики prepare вызываются в порядке LIFO, обработчики parent/child в порядке FIFO.

  6. Как сделать библиотеку fork-safe • Определите все блокировки, используемые библиотекой и порядок их захвата(L1..Ln) • Напишите функции f1, f2 и f3 • f0() {lock(L1); … lock(Ln); } • fp() { unlock(L1); … unlock(Ln); } • fc() { unlock(L1); … unlock(Ln); } • Включите вызов pthread_atfork(f0, fp, fc) в код инициализации библиотеки (секцию .init для библиотек ELF)

  7. Почему так? • Если функция использует блокировку, значит, она использует внутренние данные, которые могут быть в несогласованном состоянии • Прежде чем снимать блокировку, нам нужно дождаться завершения этой функции (если она вызвана в какой-то другой нити).

  8. Сигналы и потоки • Сигналы делятся на синхронные и асинхронные • Синхронные сигналы возникают при исполнении определенного кода в вашей программе (напр. SIGFPE при делении на 0) • Асинхронные сигналы возникают по внешним причинам

  9. Сигналы и потоки (продолжение) • синхронные сигналы обрабатываются в том потоке, в котором возникли • асинхронные сигналы обрабатываются в любом потоке • необработанные сигналы вызывают реакцию по умолчанию для всего процесса (завершение всего процесса, засыпание всего процесса и т.д.)

  10. signal(2) и sigset(2) • вызовы signal(2) и sigset(2) устанавливают глобальный обработчик сигнала (во всех нитях процесса) • установить собственный обработчик сигнала нить не может.

  11. Проблемы, связанные с сигналами • возможность мертвой блокировки • нить держит блокировку • прилетает сигнал • обработчик сигнала вызывает функцию, которая пытается захватить ту же блокировку • нить ждет сама себя • Атрибут MT-Level==Async-Signal-Safe

  12. Проблемы, связанные с сигналами (продолжение) • вызов setjmp/longjmp • если setjmp вызывался в одной нити, • а longjmp в другой • это приведет к разрушению стека (скорее всего, SIGSEGV, но не обязательно, программа может исполнить какой-то еще код и, например, записать мусор в файлы и т.д.)

  13. pthread_sigmask(3C) ИСПОЛЬЗОВАНИЕ #include <pthread.h> #include <signal.h> int pthread_sigmask(int how, const sigset_t *set, sigset_t *oset); ОПИСАНИЕ функционально аналогична sigprocmask(2), но устанавливает маску сигналов нитимаска сигналов нити наследуется при pthread_create

  14. sigprocmask/pthread_sigmask how SIG_BLOCK - Множество сигналов, на которое указывает set, будет добавлено к текущей маске. SIG_UNBLOCK - Множество set будет удалено из текущей маски. SIG_SETMASK - Текущая маска будет заменена на set.

  15. sigsetops(3C) ИСПОЛЬЗОВАНИЕ #include <signal.h> int sigemptyset(sigset_t * set); int sigfillset(sigset_t * set); int sigaddset(sigset_t * set, int signo); int sigdelset(sigset_t * set, int signo); int sigismember(sigset_t * set, int signo); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ успех - sigismember: 1 если истинно, 0 если ложно; остальные функции: 0 неуспех - -1 и errno установлена

  16. ЧТО ОЗНАЧАЕТ THREAD-SAFE ? • словосочетание thread-safe (MT-safe) не имеет общепринятого русского перевода • дословный перевод – безопасно [для] использования в многопоточной программе • стандартные библиотеки Unix и ANSI C разрабатывались до появления многопоточности • не все функции стандартных библиотек корректно работают в многопоточной среде

  17. Пример – strtok(3C) ИСПОЛЬЗОВАНИЕ #include <strings.h> char *strtok(char *restrict s1, const char *restrict s2); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ при первом вызове, возвращает первое слово в строке s1, используя разделители, указанные в s2. При втором вызове возвращает второе слово и т.д.Если достигнут конец строки, возвращает NULL

  18. Пример – strtok_r(3C) ИСПОЛЬЗОВАНИЕ #include <strings.h> char *strtok_r(char *restrict s1, const char *restrict s2, char **lasts); ПРИМЕЧАНИЕ хранит состояние строки в ячейке памяти, на которую указывает параметр lasts

  19. Примечание • В действительности, strtok в Solaris использует thread-specific data для хранения указателя на строку, поэтому в Solaris эта функция thread-safe. Но это не обязательно верно для других реализаций.

  20. Как узнать, является ли функция thread-safe? • Секция ATTRIBUTES в странице руководства ATTRIBUTES See attributes(5) for descriptions of the following attri- butes: ____________________________________________________________ | ATTRIBUTE TYPE | ATTRIBUTE VALUE | |_____________________________|_____________________________| | Interface Stability | See below. | |_____________________________|_____________________________| | MT-Level | See below. | |_____________________________|_____________________________| The strlcat() and strlcpy() functions are Stable. The remaining functions are Standard. The strtok() and strdup() functions are MT-Safe. The remain- ing functions are Async-Signal-Safe.

  21. Значения атрибута MT-level • Unsafe • Safe • MT-Safe • Async-Signal-Safe • MT-Safe with exceptions • Safe with exceptions • Fork-Safe • Cancel-Safety (Deferred- и Asynchronous-)

  22. MT Level Unsafe • Функция или группа функций использует статические или глобальные переменные, не защищенные примитивами синхронизации. • Требует явной защиты мутексами или другими средствами синхронизации

  23. MT Level Safe • Функции библиотеки сами по себе реентерабельны, но могут обеспечивать недостаточный уровень параллелизма. • Например, Safe функция может использовать внутренние мутексы, удерживаемые длительное время или в удерживаемые в промежутках между вызовами функций

  24. MT Level MT-Safe • Функция или группа функций полностью готова для работы в многопоточной среде. • Обеспечивает разумный уровень параллелизма, т.е оптимизирована так, чтобы удерживать внутренние блокировки (если они есть) минимально возможное время

  25. MT Level Async-Signal-Safe • Подразумевает MT-Safe • Может вызываться из обработчика сигнала. • Для MT-Safe это не всегда так. Если MT-Safe функция держит блокировку и в это время в той же нити вызовется обработчик сигнала, это может привести к мертвой блокировке.

  26. MT Level Fork-Safe • подразумевает MT-Safe • при fork(2) в дочернем процессе остается только та нить, которая вызвала fork • блокировки, удерживаемые исчезнувшими нитями, остаются • если библиотека MT-Safe за счет использования блокировок, она может быть не Fork-Safe

  27. Пример – readdir(3C) ИСПОЛЬЗОВАНИЕ #include <sys/types.h> #include <dirent.h> struct dirent *readdir(DIR *dirp); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ Возвращает указатель на статический буфер, перезаписывает его при последующих вызовах.

  28. readdir_r(3C) ИСПОЛЬЗОВАНИЕ #include <sys/types.h> #include <dirent.h> struct dirent *readdir_r(DIR *dirp, struct dirent *entry); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ Возвращает NULL, если достигнут конец каталога, и entry, если есть следующая запись

  29. readdir_r(3C) – стандартная форма ИСПОЛЬЗОВАНИЕ #include <sys/types.h> #include <dirent.h> cc file ... -D_POSIX_PTHREAD_SEMANTICS int readdir_r(DIR *restrict dirp, struct dirent *restrictentry, struct dirent **restrict result); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ успешное завершение – 0 ошибка - -1

  30. Более сложный пример Int fd; fd=open(fname, flags); pthread_create(thread1, …); pthread_create(thread2, …); Thread1: lseek(fd, SEEK_SET, pos1); write(fd, buf, size); Thread2: lseek(fd, SEEK_SET, pos2); write(fd, buf2, size);

  31. pread (2) ИСПОЛЬЗОВАНИЕ #include <unistd.h> int pread( int fildes, void *buf, unsigned nbyte,off_t offset); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ успех - количество прочитанных байт неуспех - -1 и errno установлена не перемещает указатель в файле

  32. pwrite (2) ИСПОЛЬЗОВАНИЕ #include <unistd.h> int pwrite( int fildes, const void *buf, unsigned nbyte,off_t offset); ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ успех - количество записанных байт неуспех - -1 и errno установлена

More Related