Может ли fnctl (F_SETOWN, <pid>) направлять сигнал на идентификатор pthread вместо идентификатора процесса? - PullRequest
0 голосов
/ 28 сентября 2018

Я разрабатываю приложение, которое собирается читать данные из последовательного порта / UART в Linux.Я пытаюсь разбудить / разблокировать pthread, который начал считывать данные, когда UART асинхронно получает данные из внешнего источника.Я пытался использовать сигнал (SIGIO) «мягкое прерывание» вместо select () или pselect (), но я не уверен, что могу получить желаемое поведение в многопоточном приложении из сигналов.

Когда я настраиваю дескриптор файла устройства, я хочу установить F_SETOWN (int), чтобы заставить ядро ​​отправлять сигнал в pthread, который я настроил для блокировки на SIGIO.

            // Configure the signal to send
            fcntl(m_fileId, F_SETSIG, m_sigNum);

            // Set to non-blocking read mode
            fcntl(m_fileId, F_SETFL, FNDELAY);

            // Bind the PID of the task which is getting the signal
            fcntl(m_fileId, F_SETOWN, m_pid);

            // Enable sending a signal when data ready
            fcntl(m_fileId, F_SETFL, O_ASYNC);

Я понял, чточто когда я писал код, для m_pid был задан идентификатор процесса, а не идентификатор pthread, а когда я проверял страницу руководства ...

Согласно справочной странице fnctl (2):

F_SETOWN (int)

Установите идентификатор процесса или идентификатор группы процессов, которые будут получать сигналы SIGIO и SIGURG для событий в файловом дескрипторе fd, на идентификатор, указанный в аргументе arg.Идентификатор процесса указывается как положительное значение;идентификатор группы процессов указан как отрицательное значение.Чаще всего вызывающий процесс указывает себя в качестве владельца (то есть arg указывается как getpid (2)).

Вместо использования getpid () для идентификатора процесса вы можете передать идентификатор pthread из вызова pthread_self (), чтобы только конкретный поток получил сигнал?

1 Ответ

0 голосов
/ 28 сентября 2018

В Linux вы можете использовать F_SETOWN_EX для нацеливания на определенный поток.

Из справочной страницы:

В ядрах 2.6.x вплоть до ядра 2.6.11 верно следующее:

Если ненулевое значение задано дляF_SETSIG в многопоточном процессе, работающем с библиотекой потоков, которая поддерживает группы потоков (например, NPTL), тогда положительное значение, заданное для F_SETOWN, имеет другое значение: вместо того, чтобы быть идентификатором процесса, идентифицирующим весь процесс, это идентификатор потокавыявление определенного потока в процессе.Следовательно, может потребоваться передать F_SETOWN результат gettid (2) вместо getpid (2), чтобы получить ощутимые результаты при использовании F_SETSIG.(В текущих реализациях потоков в Linux идентификатор потока основного потока совпадает с идентификатором процесса. Это означает, что однопоточная программа может в равной степени использовать gettid (2) или getpid (2) в этом сценарии.) Однако обратите внимание, чтооператоры в этом параграфе не применяются к сигналу SIGURG, генерируемому для внеполосных данных в сокете: этот сигнал всегда отправляется либо процессу, либо группе процессов, в зависимости от значения, заданного для F_SETOWN.

Вышеуказанное поведение было случайно удалено в Linux 2.6.12 и не будет восстановлено.Начиная с Linux 2.6.32, используйте F_SETOWN_EX для нацеливания сигналов SIGIO и SIGURG на конкретный поток.

В Linux ожидается pid/tid (идентификатор потока с точки зрения ядра; Linux частоназывает их просто pids, даже если они идентифицируют потоки, а не процессы), однако, не pthread_t.

Реализации Pthread обычно отображают pthread_t в pids внутренним образом, специфичным для реализации способом, и вы могли бывзломать вашу конкретную реализацию, чтобы получить ее.

В качестве альтернативы вы могли бы обернуть pthread_create, чтобы вставить запись хэш-таблицы отображения pthread_t-to-pid при создании потока, чтобы впоследствии вы могли отобразить pthread_t s в pid s без зависимостей от вашей реализации pthread.

(вы можете получить pid текущего потока с помощью syscall(SYS_gettid)).

...