The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]




Версия для распечатки Пред. тема | След. тема
Новые ответы [ Отслеживать ]
Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 16-Апр-09, 19:51  [смотреть все]
Здравствуете!

Можно ли как-то определить, что устройство /dev/tty кем-то открыто? Под виндой CreateFile возвращает ACCESS_DENIED, а под линуксом open открывает нормально, а хотелось бы поведения, аналогичного виндовому. Как это можно сделать?

  • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! svn, 01:59 , 17-Апр-09 (1)
    > а под линуксом open открывает нормально, а хотелось бы
    >поведения, аналогичного виндовому. Как это можно сделать?

    Сломать линукс? ))
    Блокировки в linux advisory. И это всем нравится.

    Почитай http://tldp.org/HOWTO/Serial-HOWTO.html там всё написано.
    программа использущая порт создаёт файл /var/lock/LCK..name где name - имя порта ttyS0 или что там у тебя. В файле PID твоей программы. Так все другие программы знают кто использует этот порт.

    • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 17:31 , 17-Апр-09 (3)
      >Почитай http://tldp.org/HOWTO/Serial-HOWTO.html там всё написано.
      >программа использущая порт создаёт файл /var/lock/LCK..name где name - имя порта ttyS0
      >или что там у тебя. В файле PID твоей программы. Так
      >все другие программы знают кто использует этот порт.

      Не совсем понял, /var/lock/LCK..name - именно с двумя точками?
      Нет ли какого-нибудь системного/библиотечного вызова, который атомарно проверяет наличие файла, если его нет, создает, а если есть, то считывает из него pid, проверяет, живой ли процесс с данным pid'ом, если не живой, то создает новый с pid'ом текущего процесса?

      • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! svn, 20:35 , 17-Апр-09 (7)
        >Не совсем понял, /var/lock/LCK..name - именно с двумя точками?

        Да. Ссылки не читаешь?

        >Нет ли какого-нибудь системного/библиотечного вызова, который атомарно проверяет
        >наличие файла, если его нет, создает

        Смотри опции/флаги открытия файла.

        >а если есть, то считывает из него pid, проверяет,
        >живой ли процесс с данным pid'ом, если не живой, то создает
        >новый с pid'ом текущего процесса?

        Это уже сам. Но обычно программы блокировки за собой удаляют. А на случай аварийного выключения стартовые скрипты очищают /var/lock/

        • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 23:19 , 17-Апр-09 (8)
          >>Не совсем понял, /var/lock/LCK..name - именно с двумя точками?
          >
          >Да. Ссылки не читаешь?

          Читал. Подумал, может там опечатка а вы просто скопировали, не обратив внимания ;)

          >Это уже сам. Но обычно программы блокировки за собой удаляют. А на
          >случай аварийного выключения стартовые скрипты очищают /var/lock/

          Обычно да, длжны удалять. Но вдруг программа падает (но система не перезапускается), тогда лок файл останется. Надо проверять. А мои программы падают и будут падать на этапе разработки, так что надо это как-то продумать.

          • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! vic, 01:11 , 18-Апр-09 (9)
            >[оверквотинг удален]
            >Читал. Подумал, может там опечатка а вы просто скопировали, не обратив внимания
            >;)
            >
            >>Это уже сам. Но обычно программы блокировки за собой удаляют. А на
            >>случай аварийного выключения стартовые скрипты очищают /var/lock/
            >
            >Обычно да, длжны удалять. Но вдруг программа падает (но система не перезапускается),
            >тогда лок файл останется. Надо проверять. А мои программы падают и
            >будут падать на этапе разработки, так что надо это как-то продумать.
            >

            в lock файле обычно pid процесса, проверит наличие процесса не составляет труда, нет процесса - смело удаляем файл и создаем свой.


    • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 17:34 , 17-Апр-09 (5)
      И еще, насколько этот механизм блокировки поддерживается в разном софте? Следует ли кто-нибудь данным правилам?
    • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 20:07 , 20-Апр-09 (11)
      Сделал как умные люди советовали, через блокировку в /var/lock.
      Возник такой вопрос - лок файл создается с парвами --------- (т.е. ничего нельзя с ним делать). Голову сломал, не пойму, где косяк. Код такой:

      bool tryMakeNewExclusiveLock( const char* lockFileName)
         {
          PID_T pid = getpid();
          char strPid[64];
          char strTick[64];
          sprintf(strPid, "%u", pid);
          sprintf(strTick, "%u", (unsigned)cliGetTickCount());

          char* uniqName = (char*)_alloca( strlen(lockFileName) + strlen(strPid) + strlen(strTick) + 16 );
          strcpy( uniqName, lockFileName );
          strcat( uniqName, "." );
          strcat( uniqName, strPid );
          strcat( uniqName, "." );
          strcat( uniqName, strTick );

          mode_t prevMask = umask(0777);
          //std::cout<<"prevMask: "<<prevMask<<"\n";
          //std::cout<<"newMask : "<<umask(0777)<<"\n";

          mode_t creatMode = S_IRWXU|S_IRWXG|S_IRWXO;
          int newLockFile = ::open( uniqName, O_CREAT|O_RDWR, creatMode );
          if (newLockFile==-1)
             {
              return false; // failed to lock
             }
          //std::cout<<"newLockFile: "<<newLockFile<<"\n";
          size_t bytesToWrite = strlen(strPid);
          if (::write(newLockFile, strPid, bytesToWrite )==-1)
             {
              //std::cout<<"Write error: "<<errno<<" "<<strerror(errno)<<"\n";
              //std::cout<<"newLockFile: "<<newLockFile<<"\n";
              ::close(newLockFile);
              ::unlink(uniqName);
              ::umask(prevMask);
              return false;
             }
          ::close(newLockFile);

          bool res = false;
          if (::link(uniqName, lockFileName)==-1)
             {
              struct stat s;
              ::stat(uniqName, &s);
              if (s.st_nlink>=2) res = true;      
             }
          else
             {
              res = true;
             }
          
          ::unlink(uniqName);
          ::umask(prevMask);
          return res;
         }

      • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 20:26 , 20-Апр-09 (12)
        Ой затупил, umaks же инвертируется перед объединением. Вопрос снят ;)
      • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! vic, 10:20 , 21-Апр-09 (13)
        Ужасы С++, да еще с ошибками :((
        Читайте исходники опенпроектов, каждый день.
        • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 21:43 , 21-Апр-09 (14)
          >Ужасы С++, да еще с ошибками :((

          В чем ужасы, и в чем ошибки, в двух словах, если не сложно?

          >Читайте исходники опенпроектов, каждый день.

          Пошел читать ;)
          Вот где ужасы-то обычно гнездятся ;)

          • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! vic, 03:35 , 22-Апр-09 (15)
            >>Ужасы С++, да еще с ошибками :((
            >В чем ужасы, и в чем ошибки, в двух словах, если не сложно?

            1. ужас в том что вроде как С++, а реально С кошмарный. Если уж С++, то и использовать для большей части действий средства C++ (стримы, строки, работа с файлами). Можно же реализовать большую часть кода (или весь) не опускаясь до работы с системными вызовами.
            2. первые 10 строк (формирование названия файла) заменяются одним/двумя snprintf(), или std::string если уж С++.
            3. вы используете не юниксовый способ названия переменных и функций, поэтому читать непривычно. Обратите свое внимание на code styles принятые в *nix, gnu.
            4. ошибка при проверки write(), в проверке надо учитывать и положительный результат тоже:
                if (write(newLockFile, strPid, bytesToWrite) != bytesToWrite) {...}
            write() может вернуть меньше чем заявленное len.
            5. злоупотребление оператором ::
            6. _alloca() - зло.
            7. что за муть с линками?
            8. и ваще название функции вводит в заблужение, какой такой Exclusive Lock)) нету его в линухе.
            9. лучше open() либо с флагами O_CREAT|O_WRONLY|O_TRUNC, либо creat(). Вы же ни читаете в данном случае.
            10. <- раз подумать прежде чем игнорить маску (тут это вообще не нужно). в данном куске кода при open failed маска у вас не восстанавливается.

            ЗЫ лучше всего взять и посмотреть исходники программ в которых уже реализована нужная функция, благо их полно для изучения.


            • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! marty37, 11:01 , 22-Апр-09 (16)
              Спасибо за коментарий. Кое в чем не согласен, пропробую оправдаться. Можете проигнорировать, если нет желания дискутировать ;)

              >1. ужас в том что вроде как С++, а реально С кошмарный.
              >Если уж С++, то и использовать для большей части действий средства
              >C++ (стримы, строки, работа с файлами). Можно же реализовать большую часть
              >кода (или весь) не опускаясь до работы с системными вызовами.

              Потоки C++ тормоза, и я страюсь обходится без них. Системные вызовы не считаю злом.

              >3. вы используете не юниксовый способ названия переменных и функций, поэтому читать
              >непривычно. Обратите свое внимание на code styles принятые в *nix, gnu.

              Я пишу под *nix и под Win32, coding style мой собственный, принятый в проекте.

              >4. ошибка при проверки write(), в проверке надо учитывать и положительный результат
              >тоже:

              +

              >5. злоупотребление оператором ::

              +

              >6. _alloca() - зло.

              Наоборот, считаю его добром, которое быстро выделяет память и позволяет не заботиться о ее освобождении. Если есть ссылки на материалы, в которых аргументироно объясняется, что это зло, с интересом почитаю.

              >7. что за муть с линками?

              man 2 open говорит, что лучше делать так для лок файлов.

              >8. и ваще название функции вводит в заблужение, какой такой Exclusive Lock))
              >нету его в линухе.

              +

              >9. лучше open() либо с флагами O_CREAT|O_WRONLY|O_TRUNC, либо creat(). Вы же ни
              >читаете в данном случае.

              +. Сначала собирался читать, потом передумал.

              >10. <- раз подумать прежде чем игнорить маску (тут это вообще не
              >нужно). в данном куске кода при open failed маска у вас
              >не восстанавливается.

              +. Спасибо, пропустил.
              >
              >ЗЫ лучше всего взять и посмотреть исходники программ в которых уже реализована
              >нужная функция, благо их полно для изучения.

              Я не большой знаток софта под *nix, на вскидку не могу ничего придумать, куда бы посмотреть.

              • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! vic, 15:27 , 22-Апр-09 (17)
                >Потоки C++ тормоза, и я страюсь обходится без них. Системные вызовы не
                >считаю злом.

                в данной функции использование стримов для формирования названия файла и записи в него никак не влияют на скорость.
                ну а для формирования имени файла snprintf(name, max_name_len, "%s.%d.%d.ded_moroz", ...);
                с проверкой, читабельнее чем куча strcat().

                >>6. _alloca() - зло.
                >Наоборот, считаю его добром, которое быстро выделяет память и позволяет не заботиться
                >о ее освобождении. Если есть ссылки на материалы, в которых аргументироно
                >объясняется, что это зло, с интересом почитаю.

                а c точки зрения внесение последующих изменений другим программистом - будет порождать различные ошибки в внесенном коде. Также возможна атака на стек (он не настолько резиновый), т.к. выделяемый размер зависит от strlen(lockFileName). Еще эта функция неидиоматичная, народ будет спотыкаться о нее при чтений кода + необходимость держать ее в голове до завершающей '}'. А так же не все умеют с ней правильно работать. Кстати, можно и char str[strlen(a)]; использовать, не так неожиданно будет. В общем тут минус как у goto, сам по себе оператор не плохой, а вот использование хромает, да и риски ошибок большие :)

                http://blogs.sun.com/ambiguous/entry/a_safe_way_of_using - тут есть кое-что.
                http://www.gnu.org/software/hello/manual/libc/Advantages-of-... - плюсы
                http://www.gnu.org/software/hello/manual/libc/Disadvantages-... - минусы

                опять же в данном случае нет смысла гнаться за скоростью путем использования небезопасных функций.

                >>7. что за муть с линками?
                >man 2 open говорит, что лучше делать так для лок файлов.

                это он про тот случай если O_EXCL не работает (NFS ниже какой-то версии) при межхостовых блокировках, у вас случай проще, com-порт локален и файл блокировки локален. Просто использовать O_EXCL.

                >>9. лучше open() либо с флагами O_CREAT|O_WRONLY|O_TRUNC, либо creat(). Вы же ни
                >>читаете в данном случае.
                >+. Сначала собирался читать, потом передумал.

                та я хотел чтобы пунктов было 10, вот и стал придираться :)

                >Я не большой знаток софта под *nix, на вскидку не могу ничего
                >придумать, куда бы посмотреть.

                я тоже, но тот же minicom, или тот же ppp :)

  • Как определить, что COM порт (/dev/tty) уже кем-то открыт?, !*! Аноним, 11:22 , 17-Апр-09 (2)



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру