Как я могу позволить потоку 2 общаться на порте, который я открыл в потоке 1?

0

Я пытаюсь связаться с одним и тем же портом, используя два разных потока в программе CLI C++ (работает в Windows, но не использует Windows API). Порт представляет собой USB-порт (который ведет к конвертеру в RS-232, а затем к другому устройству). Я могу успешно установить связь портов в main потоке с использованием OpenCom() и Transmit(), предоставляемых в DLL производителем этих устройств.

Затем я вызываю newThreadFunc() (определенный в другой DLL), который запускается в отдельном потоке (пусть он вызывает поток обратного вызова) и вызывает функцию обратного вызова. В этой функции обратного вызова я снова вызываю Transmit(), но теперь он возвращается с ошибкой (определенной DLL): "Порт не готов (CreateFile)".

Вот упрощенный псевдокод:

#include "Device.h"            // contains OpenCom() & Transmit()

const short comPort = 3; // COM port number (global)

int main(int argc, char* argv[]) {

    OpenCom(comPort);          // Open the port
    Transmit(command);         // where "command" represents some command

    newThreadFunc(taskHandle); // Creates new "callback thread" and calls callbackFunc
    getchar();                 // wait while other thread runs
    return 0;
}

signed long __cdecl callbackFunc (params) {
    Transmit(command);         // error: "Port not ready (CreateFile)"
    OpenCom(comPort);          // error: "Port already open (CreateFile)"
}

Если я вызову OpenCom в потоке обратного вызова, я получу эту ошибку: "Порт уже открыт (CreateFile)". Таким образом, поток обратного вызова может видеть, что порт открыт, но не может связываться с ним. Я знаю, что мне нужно как-то управлять связью портов с мьютексом или аналогичным, но почему причина, по которой поток обратного вызова не может связываться на порту? И как я могу позволить потоку обратного вызова связываться на порт, который я открыл в основном потоке?

Теги:
multithreading
serial-port
thread-synchronization

1 ответ

4

Серийные порты - очень простые устройства, они просто поддерживают непрозрачный поток байтов. Нет протокола, позволяющего двум потокам или двум приложениям совместно использовать порт. Ничего подобного TCP, который позволяет логическое соединение с определенным номером порта в одном сетевом соединении. В модели OSI последовательный порт занимает нижний, физический уровень. Без каких-либо стандартов, которые когда-либо возникали для создания слоев поверх него, никто никогда не соглашался с тем, какой слой должен выглядеть. Протокол Hayes AT для модемов до сих пор.

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

  • 0
    Правильно ли я понял? Если я открою порт в потоке 1, нет способа связаться с ним в потоке 2, не закрыв сначала его в потоке 1? Или вы имеете в виду, что это должно быть возможно с мьютексом?
  • 0
    Порт может быть открыт только один раз, жесткое требование. Надеюсь, вы уже поняли, почему существует это требование. Если вы хотите использовать мьютекс, чтобы гарантировать, что только один поток может когда-либо считывать данные из порта, тогда, да, это может сработать.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню