На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела *nix / gcc / Eclipse / Qt / wxWidgets / GTK+
  • При создании темы ОБЯЗАТЕЛЬНО указывайте версию тулкита / библиотеки / компилятора.
  • Перед тем как задать вопрос, сформулируйте его правильно, чтобы вас могли понять.
  • Нарушение Правил может повлечь наказание со стороны модераторов.


Полезные ссылки:
user posted image Boost по-русски
user posted image Qt по-русски
Модераторы: archimed7592
  
> Fork приложения на сетевом диске
    Хз в тот ли раздел пишу - модеры поправьте, если что.
    Суть такая, есть приложение в виде одного екзешника/бинарника весом под 200Мб. Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы.
    Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса. Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети? :-?
      Странно, что она качается.
      Я на сколько знаю, команда fork вызывает копирование процесса в памяти и один процесс пускается по одной ветке, другой по другой.
      При этом, уже обученный до форка процесс является уникальным, поэтому и копируется, полностью, а не запускается новый. Вытягивать его с диска в общем-то не логично. Может что с кодом не так? Он точно после форка содержит память родительского процесса?
      Может просто по ошибке вылетает и перезапускается, вследствие чего и тянет файлик заново..?
        Цитата _lcf_ @
        Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети?

        Копируй его на локальный диск перед каждым запуском и все.
        Хотя в линуксе форк не должен тормозить в любом случае. Скорее всего там проблема в чем–то другом.
          Цитата simsergey @
          Странно, что она качается.

          ничего странного так и работает. при форке нужен физический файл.
          Цитата simsergey @
          Может просто по ошибке вылетает и перезапускается, вследствие чего и тянет файлик заново..?

          форк так контролируемый, как раз чтобы снизить негативные последствия возможных падений.
          Цитата Олег М @
          Копируй его на локальный диск перед каждым запуском и все.

          это определяется системной политикой каждой конторы, использующей наш софт, где-то могут быть заблокированы локальные диски на запись. и да, в линуксе проблема менее ощутима, но это не избавляет от решения проблемы в целом.

          Добавлено
          по большому счёту проблема на винде из-за тупого кэша, да...
            Стойте-ка.
            1. А проблема на винде? Именно при форке?
            2. И оправдан ли такой объём бинарника? Может стоит посмотреть в сторону того, чтоб вытащить из него отладочные символы и положить рядышком?
              Цитата negram @
              1. А проблема на винде? Именно при форке?

              ну да, процесс слегка эээ подвисает, пока качает 200 метров по сети, с учетом того, что пользователей могут быть десятки - нагрузка на сеть становится не кислой, так как форкается приложение довольно часто.
              Цитата negram @
              2. И оправдан ли такой объём бинарника?

              политика компании - один екзешник, никаких либ и зависимостей, ноу айти реквест :-? а в последнем релизе туда еще и все мануалы запихали, что увеличило объем в два раза :)
                Хм...
                Вроде бы тема к сетевому программированию никаким боком. :)
                Ну да ладно, попробую свои пять копеек положить на кон...
                Цитата negram @
                1. А проблема на винде? Именно при форке?

                Я что то помню, вроде fork() в винде отсутствует ваще...как класс.
                Аналогом всегда была CreateProcess().
                Цитата _lcf_ @
                Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса.


                Цитата _lcf_ @
                Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы.

                Интересная постановка проблемы.
                1. Оригинал екзешника лежит на сетевом диске.
                2. Пользователь скачивает экзешник и запускает.
                3. В винде создается процесс и работает автономно. Где то внутри работающего процесса есть код, который должен создать копию этого процесса. CreateProcess это и должен сделать, и обращения к сетевому диску не требуется
                4. В никсах пользователь скачивает экзкшник к себе. Shell оригинальной машины пользователя форкает процесс и таким образом запускает его. Внутри запущенного процесса новая копия создается тем форком, который внутри родительского кода. Никакого обращения к сетевому диску не требуется.
                По логике нигде не нужны повторные обращения к сетевому диску.
                Где ошибка в этих рассуждениях? :(
                M
                Тему все таки перемещу :) Пусть спецы посмотрят
                Сообщение отредактировано: Oleg2004 -
                  Цитата Oleg2004 @
                  Аналогом всегда была CreateProcess

                  А в чем там аналогия?

                  Добавлено
                  Цитата Oleg2004 @
                  Где ошибка в этих рассуждениях?

                  Насколько я понял, пользователь не скачивает exe–шник, а запускает его с удаленнго диска. Немного разные вещи
                    Олег М
                    Цитата _lcf_ @
                    Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска.

                    Написано - скачивается...
                    Понятно, что запустить чужое приложение на ЧУЖОЙ машине - это одно.
                    Но ТС ясно пишет - скачивает. :(
                    Вот я и пытаюсь понять, как это ДОЛЖНО!приводить к повышенной сетевой активности.

                    Цитата Олег М @
                    А в чем там аналогия?

                    В создании нового процесса. В винде форка нет, чтобы его создать.
                    Сообщение отредактировано: Oleg2004 -
                      Цитата Oleg2004 @
                      В создании нового процесса. В винде форка нет, чтобы его создать.

                      Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла
                        ну говоря скачивается имелось ввиду что в оперативку. файл физически естесно на сетевом диске.
                        ну и да в винде createprocess, а не форк, да и... в линуксе тоже. просто там кеш для сетевых дисков адекватно работает.
                        в общем, пришли к выводу что на винде при первом запуске копировать приложение во временную папку.
                          Короче, дело такое.
                          Код процесса -- выгружаемая память. И выгружается он не в своп, а просто нафиг. Если что, можно снова с exe-шника подгрузить. Так вот, что в линуксе, что в винде возможна ситуация, что форкнутый процесс полезет на диск за кодом. Но если форк честный и проблем с памятью нет, то диск в общем-то не нужен, и странички памяти могут хоть копиорваться, хоть реюзатся до посинения.
                          Другое дело, что насколько я знаю, в винде форк реализован через тот же CreateProcess (поправьте меня). И он всегда загружает образ с диска (ну либо с кеша файловой системы, хотя сомнительно что все 200 метров останутся в этом самом кеше).
                            в винде кэшируется только локальная память, с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен.
                              Цитата Олег М @
                              Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла

                              Проблема в таргеттинге. Т.е. в семантике.
                              Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса.
                              Вот вам простой пример
                              ExpandedWrap disabled
                                /*Тут куча инклюдов, опускаем*/
                                #define MYPORT 3490     /* Порт, на который будет идти соединение*/
                                #define BACKLOG 10 /* Сколько подключений может быть в очереди */
                                int main()
                                   {
                                int sd, newsd; /* Слушаем на сокете sd, новое подключение на сокете newsd */
                                struct sockaddr_in my_addr;/* Серверная адресная информация */
                                struct sockaddr_in their_addr;  /* Адресная информация запрашивающей стороны (клиента) */
                                int sin_size;
                                /* Создаем  Интернет-сокет, ориентированный на соединение*/
                                if ((sd = socket (AF_INET, SOCK_STREAM, 0)) == -1)
                                {perror ("socket");exit (1); }
                                my_addr.sin_family = AF_INET;   /* В порядке байтов хоста */
                                my_addr.sin_port = htons (MYPORT);/* short, в порядке байтов сети */
                                /* Авто-заполнение IP-адресом серверного сетевого интерфейса */
                                my_addr.sin_addr.s_addr = INADDR_ANY;
                                bzero(&(my_addr.sin_zero), 8);/* Обнуляем остальную часть struct */
                                /* Связываем только-что созданный сокет с его локальным адресом */
                                if (bind(sd, (struct sockaddr *)&my_addr, sizeof (struct sockaddr)) == -1)
                                {perror ("bind");exit (1);   }
                                /* Организуем очередь прослушивания сети на порту MYPORT */
                                if (listen (sd, BACKLOG) == -1)
                                {perror ("listen");exit (1);}
                                while(1) /* Главный цикл accept()*/
                                {  
                                sin_size = sizeof (struct sockaddr_in);
                                if ((newsd = accept (sd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
                                {  perror ("accept"); continue; /* продолжаем прием*/   }
                                /* Приняли запрос на соединение и принимаем решение ответить на него*/
                                printf (" сервер: Принял соединение от %s\n ", inet_ntoa (their_addr.sin_addr));
                                if(!fork())
                                [B]{/* Мы находимся в дочернем порожденном процессе */
                                close (sd); /* Закрываем дескриптор слушающего сокета, он потомку не нужен */
                                /* Потомок наследует все файловые дескрипторы родителя, а значит, и newsd */
                                /* Теперь таких сокетов два - в каждом процессе по одному */
                                /* Шлем клиенту 14 байтов */
                                if (send(newfd, " Привет, мир! \n", 14, 0) == -1)perror ("send");
                                close(newsd);/* Закрываем сокет newsd  в порожденном процессе */
                                exit (0);/* Завершаем передачу данных из процесса потомка */
                                }   /* Здесь заканчивается текст процесса программы-потомка*/[/B]
                                close (newsd);  /* Закрываем сокет newsd – родитель в нем не нуждается */
                                while (waitpid (-1, NULL, WNOHANG) > 0);    /* Очищаем порожденные процессы */
                                }/*Конец цикла accept()*/
                                return 0;  
                                }/* Завершаем процесс сервера */

                              Так вот, то что болдом - (Блин, болд не работает в срр) это и есть текст программы нового дочернего процесса. И - ВСЕ.
                              С вызова форка одновременно исполняются теперь два процесса одновременно. И говорить о копировании тут смысла нет. Ваще. Просто процесс-потомок наследует большую часть атрибутов своего родителя, и в частности, открытые файлы (порожденный процесс обладает копией дескрипторов файлов, открытых его родителем).
                              Однако порожденный процесс после вызова fork() с помощью функции exec() может запустить совершенно новый исполнимый файл, при этом его предыдущее "родительское" содержание в памяти заменяется текстом нового файла.
                              Так что вопрос в семантике форка. Это - не копирование, а разветвление. Потому и говорим, что Винда и никсы обладают совершенно разными подходами к вопросам запуска новых процессов.
                              Сообщение отредактировано: Oleg2004 -
                                Цитата Oleg2004 @
                                Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса.

                                Что значит разветвляет?
                                Процесс - это исполняемый код и память, ну и какие-то ресурсы, типа хэндлов. Насколько я понимаю, линукс, в fork() ничего этого не копирует, а просто увеличивает счётчики или типа того. Windows так не умеет.
                                  Цитата _lcf_ @
                                  в винде кэшируется только локальная память, с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен.
                                  Проблема решается технологией BranchCache.
                                  Краткое описание, взял с хабра:
                                  Цитата
                                  BranchCache – технология кэширования, встроенная в Windows 7 и Windows Server 2008 R2, и призванная оптимизировать (сократить) сетевой трафик, передаваемый по WAN-каналам связи. Соответственно, основная сфера применения BranchCache – организации с филиалами и удаленными офисами, которые связаны между собой и центральным офисом сравнительно медленными линиями передачи данных.
                                  BranchCache поддерживает кэширование HTTP- и SMB-трафика. При этом на клиентских компьютерах должна быть установлена Windows 7 (редакции Ultimate или Enterprise, в других редакциях BranchCache не работает), а на серверах – Windows Server 2008 R2. Таким образом, BranchCache работает только в связке Windows 7 + Windows Server 2008 R2.

                                  Глупо это, хранить вообще все в одном исполнительном файле и потом форкаться. Нафиг?
                                  По нормальному тогда уж если все с собой тягается, то и форкающийся код стоит вынести в отдельный exe, порождать его форкать на здоровье. А связь с основным exe уж через pipe поддерживать..
                                  В таком случае форкаться будет только то что нужно, весь хлам будет висеть в оперативной памяти, и вдобавок к этому, если еще и не все форкается функцией, не придется заново воссоздавать объекты (там вам виднее, конечно же).
                                  Сообщение отредактировано: simsergey -
                                    Цитата Олег М @
                                    Что значит разветвляет?

                                    Fork - это вилка, или разветвление.
                                    Я вам привел пример
                                    Цитата Олег М @
                                    Насколько я понимаю, линукс, в fork() ничего этого не копирует, а просто увеличивает счётчики или типа того. Windows так не умеет.

                                    Все по сути сложнее. Вы же видели пример - текст программы - один
                                    но содержит код родителя и код потомка. И когда в коде родителя выполнен форк, с этого момента в системе уже два одновременно работающих процесса.
                                    Насчет счетчиков каких таких?
                                    В никсах основной процесс имеет свои таблицы файлов. В них много всего. В том числе и сокеты к примеру - они рассматриваются как псевдофайлы. Потомок делает копию таблицы родителя и работает с ней. В примере все четко показано - как родитель уничтожает указатель на сокет в своей таблице, ему с этим сокетом не надо работать. Тогда как у потомка эта запись о сокете остается. В его копии. Ну это про файлы и прочая. Есть много чего еще что копируется в процесс потомка...
                                    Почитайте "Управление процессами в UNIX" Р. Стивенса...Классика.
                                    Сообщение отредактировано: Oleg2004 -
                                      Цитата Oleg2004 @
                                      Насчет счетчиков каких таких?
                                      В никсах основной процесс имеет свои таблицы файлов. В них много всего. В том числе и сокеты к примеру - они рассматриваются как псевдофайлы. Потомок делает копию таблицы родителя и работает с ней. В примере все четко показано - как родитель уничтожает указатель на сокет в своей таблице, ему с этим сокетом не надо работать. Тогда как у потомка эта запись о сокете остается. В его копии. Ну это про файлы и прочая. Есть много чего еще что копируется в процесс потомка...

                                      Счётчики использования страниц памяти, использования хэндлов.
                                      Т.е. когда ты создаёшь копию процесса, зачем тебе копировать его код? Он read-only, поэтому достаточно увеличить счётчик соответствующих страниц памяти и пользоваться ими.

                                      Цитата Oleg2004 @
                                      Fork - это вилка, или разветвление.
                                      Я вам привел пример


                                      Я знаю как переводится слово fork.
                                      Чтобы дублировать процесс, нужно скопировать его код и память и запустить поток. Чтобы этот процесс продолжил работать с того же места нужно ещё скопировать регистры потока.
                                        Цитата simsergey @
                                        Проблема решается технологией BranchCache.

                                        ни черта она не решается, у нас поддержка вынь 7,8 и 10
                                        Цитата simsergey @
                                        Глупо это, хранить вообще все в одном исполнительном файле и потом форкаться. Нафиг?

                                        я уже все описывал в теме :-?
                                        Олег М, simsergey, Oleg2004 вы можете и дальше за форк ченить поговорить
                                        Цитата _lcf_ @
                                        ну и да в винде createprocess, а не форк, да и... в линуксе тоже.

                                        подразумевалось, что конкретно у нас форк не используется, просто так все говорят...
                                          Цитата _lcf_ @
                                          ни черта она не решается
                                          То есть, почему?
                                          Единственное, этот компонент надо поставить, он по умолчанию не установлен, и доступен правда не во всех редакциях.
                                            simsergey
                                            Цитата simsergey @
                                            Таким образом, BranchCache работает только в связке Windows 7 + Windows Server 2008 R2.

                                            это раз. хотя может сейчас и есть поддержка новых версий винды.
                                            ну а второе, это значит мы своим клиентам должны сказать - ну вы там админов своих пните, чтобы они тулзу какую-то настроили :whistle:
                                              Цитата _lcf_ @
                                              Олег М, simsergey, Oleg2004 вы можете и дальше за форк ченить поговорить

                                              Да уж нет, увольте. :)
                                              Основная проблема принципиально ясна, и как решить ее вы уже предложили.
                                              Одно правда я так и не допонял
                                              Ваши юзвери пользуют и винду и никсы?
                                                Цитата _lcf_ @
                                                ну а второе, это значит мы своим клиентам должны сказать - ну вы там админов своих пните, чтобы они тулзу какую-то настроили

                                                Не, ну вы можете им, клиентам, сказать, что это у вашей компании политика такая, чтоб всё тормозило, надо потерпеть. Они поймут.
                                                  Цитата _lcf_ @
                                                  ну а второе, это значит мы своим клиентам должны сказать - ну вы там админов своих пните, чтобы они тулзу какую-то настроили
                                                  Это нормальная практика, выставить системные требования для ОС.
                                                  С другой стороны - это плата за упрямство держать все в одном .exe, другое дело, как я писал выше, стартовать свою систему, вытаскивать все что есть в память, а там уже стартовать другие свои exe, связываться с ними и т.д., если есть такая необходимость форкать процессы в винде, зная что они не форкаются, а создаются заново.
                                                  Почему потоки не использовать? Приложению требуется работать в распределенных системах с поддержкой миграции процессов (без поддержки миграции по нодам потоков) ?

                                                  Впрочем, для вашей задачи я предложил решение - BranchCache, exe будет стартовать из кэша на конечной машине, второй раз.
                                                  Это в общем-то решение "из коробки", остальное - это переделка вашего кода. Это изначально не ровное решение.
                                                    Цитата Oleg2004 @
                                                    Ваши юзвери пользуют и винду и никсы?

                                                    в основном винда. но есть пользователи кластеров - узлы на никсах, терминалы на винде. разработчики все на никсах (почти).
                                                    Цитата Олег М @
                                                    Они поймут.

                                                    решение уже реализовано, тут хоть кто-нибудь читать умеет? :wall:

                                                    Добавлено
                                                    Цитата simsergey @
                                                    Почему потоки не использовать?

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

                                                    Цитата simsergey @
                                                    остальное - это переделка вашего кода.

                                                    это несравнимо проще, чем пытаться напрячь людей по всему миру ;)
                                                    Сообщение отредактировано: _lcf_ -
                                                      Цитата _lcf_ @
                                                      решение уже реализовано, тут хоть кто-нибудь читать умеет?

                                                      Звучит примерно как - мы уже привинтили к своему велосипеду квадратные колёса и нам нужно только чтоб он поехал.

                                                      Здесь единственным решением скорее всего будет сохранять файл на локальном диске. Как это сделать - другой вопрос.
                                                      Наверняка есть возможность в обоих системах настроить кэширование файла или какой-нибудь оффлайн доступ для расшаренных папок.
                                                      Ну и в любом случае что-то придётся настраивать на клиентах.
                                                      Сообщение отредактировано: Олег М -
                                                        Олег М, ну вы явно не читаете что я пишу.
                                                        Цитата Олег М @
                                                        Здесь единственным решением скорее всего будет сохранять файл на локальном диске.

                                                        так и сделано.
                                                        Цитата Олег М @
                                                        Как это сделать - другой вопрос.

                                                        в никсах положен болт, там прекрасно кешируются сетевые данные.
                                                        для винды проверяется сетевой ли файл (PathIsNetworkPath), если сетевой и номер ревизии не совпадает(он в имени локальном отображен), то тянется на диск.
                                                        Цитата Олег М @
                                                        Ну и в любом случае что-то придётся настраивать на клиентах.

                                                        ничего не придется. будут папочку темп раз в год чистить. много жалоб будет, будем сами чистить, если файлов больше 5, например.
                                                          Цитата _lcf_ @
                                                          его не придется. будут папочку темп раз в год чистить. много жалоб будет, будем сами чистить, если файлов больше 5, например

                                                          Т.е. проблемы уже нет?
                                                            Цитата _lcf_ @
                                                            в основном винда. но есть пользователи кластеров - узлы на никсах, терминалы на винде. разработчики все на никсах (почти).

                                                            Понятно.
                                                            Вопросов больше нет... :)
                                                              в общем да, проблему можно считать решенной. но если найдется способ программно объяснить системе, что неплохо бы кешировать сетевые данные...
                                                              но я так понимаю, что это уже задача ФС, как у NFS, например.
                                                                Цитата _lcf_ @
                                                                с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен

                                                                А покурим-ка маны по smbfs (mount.cifs):

                                                                Цитата
                                                                cache=
                                                                Cache mode. See the section below on CACHE COHERENCY for details. Allowed values are:
                                                                • none: do not cache file data at all
                                                                • strict: follow the CIFS/SMB2 protocol strictly
                                                                • loose: allow loose caching semantics
                                                                The default in kernels prior to 3.7 was "loose". As of kernel 3.7 the default is "strict".

                                                                И видим, что SMB2 всеж как-то кэширование поддерживает. Для *nix SMB реализован в виде обычной файловой системы (smbfs). А вот дальше, как именно реализовано кеширование - рекомендую погуглить самостоятельно.
                                                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                                                0 пользователей:


                                                                Рейтинг@Mail.ru
                                                                [ Script execution time: 0,0738 ]   [ 17 queries used ]   [ Generated: 23.04.24, 06:54 GMT ]