Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.219.130.41] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
Хз в тот ли раздел пишу - модеры поправьте, если что.
Суть такая, есть приложение в виде одного екзешника/бинарника весом под 200Мб. Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы. Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса. Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети? |
Сообщ.
#2
,
|
|
|
Странно, что она качается.
Я на сколько знаю, команда fork вызывает копирование процесса в памяти и один процесс пускается по одной ветке, другой по другой. При этом, уже обученный до форка процесс является уникальным, поэтому и копируется, полностью, а не запускается новый. Вытягивать его с диска в общем-то не логично. Может что с кодом не так? Он точно после форка содержит память родительского процесса? Может просто по ошибке вылетает и перезапускается, вследствие чего и тянет файлик заново..? |
Сообщ.
#3
,
|
|
|
Цитата _lcf_ @ Есть ли какой-нибудь способ/механизм "объяснить" приложению/системе, что не обязательно при каждом форке качать копию по сети? Копируй его на локальный диск перед каждым запуском и все. Хотя в линуксе форк не должен тормозить в любом случае. Скорее всего там проблема в чем–то другом. |
Сообщ.
#4
,
|
|
|
Цитата simsergey @ Странно, что она качается. ничего странного так и работает. при форке нужен физический файл. Цитата simsergey @ Может просто по ошибке вылетает и перезапускается, вследствие чего и тянет файлик заново..? форк так контролируемый, как раз чтобы снизить негативные последствия возможных падений. Цитата Олег М @ Копируй его на локальный диск перед каждым запуском и все. это определяется системной политикой каждой конторы, использующей наш софт, где-то могут быть заблокированы локальные диски на запись. и да, в линуксе проблема менее ощутима, но это не избавляет от решения проблемы в целом. Добавлено по большому счёту проблема на винде из-за тупого кэша, да... |
Сообщ.
#5
,
|
|
|
Стойте-ка.
1. А проблема на винде? Именно при форке? 2. И оправдан ли такой объём бинарника? Может стоит посмотреть в сторону того, чтоб вытащить из него отладочные символы и положить рядышком? |
Сообщ.
#6
,
|
|
|
Цитата negram @ 1. А проблема на винде? Именно при форке? ну да, процесс слегка эээ подвисает, пока качает 200 метров по сети, с учетом того, что пользователей могут быть десятки - нагрузка на сеть становится не кислой, так как форкается приложение довольно часто. Цитата negram @ 2. И оправдан ли такой объём бинарника? политика компании - один екзешник, никаких либ и зависимостей, ноу айти реквест а в последнем релизе туда еще и все мануалы запихали, что увеличило объем в два раза |
Сообщ.
#7
,
|
|
|
Хм...
Вроде бы тема к сетевому программированию никаким боком. Ну да ладно, попробую свои пять копеек положить на кон... Цитата negram @ 1. А проблема на винде? Именно при форке? Я что то помню, вроде fork() в винде отсутствует ваще...как класс. Аналогом всегда была CreateProcess(). Цитата _lcf_ @ Приложение написано на С++/Qt, проблема актуальна как для винды так и для линукса. Цитата _lcf_ @ Естесно это приводит к тому, что приложение скачивается с сетевого диска. И все бы ничего, да вот только приложение при своей работе активно форкается, а это уже приводит к существенным сетевым нагрузкам и увеличивает время работы. Интересная постановка проблемы. 1. Оригинал екзешника лежит на сетевом диске. 2. Пользователь скачивает экзешник и запускает. 3. В винде создается процесс и работает автономно. Где то внутри работающего процесса есть код, который должен создать копию этого процесса. CreateProcess это и должен сделать, и обращения к сетевому диску не требуется 4. В никсах пользователь скачивает экзкшник к себе. Shell оригинальной машины пользователя форкает процесс и таким образом запускает его. Внутри запущенного процесса новая копия создается тем форком, который внутри родительского кода. Никакого обращения к сетевому диску не требуется. По логике нигде не нужны повторные обращения к сетевому диску. Где ошибка в этих рассуждениях? M Тему все таки перемещу Пусть спецы посмотрят |
Сообщ.
#8
,
|
|
|
Цитата Oleg2004 @ Аналогом всегда была CreateProcess А в чем там аналогия? Добавлено Цитата Oleg2004 @ Где ошибка в этих рассуждениях? Насколько я понял, пользователь не скачивает exe–шник, а запускает его с удаленнго диска. Немного разные вещи |
Сообщ.
#9
,
|
|
|
Олег М
Цитата _lcf_ @ Приложение лежит на сетевом диске откуда и запускается юзверями. Естесно это приводит к тому, что приложение скачивается с сетевого диска. Написано - скачивается... Понятно, что запустить чужое приложение на ЧУЖОЙ машине - это одно. Но ТС ясно пишет - скачивает. Вот я и пытаюсь понять, как это ДОЛЖНО!приводить к повышенной сетевой активности. Цитата Олег М @ А в чем там аналогия? В создании нового процесса. В винде форка нет, чтобы его создать. |
Сообщ.
#10
,
|
|
|
Цитата Oleg2004 @ В создании нового процесса. В винде форка нет, чтобы его создать. Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла |
Сообщ.
#11
,
|
|
|
ну говоря скачивается имелось ввиду что в оперативку. файл физически естесно на сетевом диске.
ну и да в винде createprocess, а не форк, да и... в линуксе тоже. просто там кеш для сетевых дисков адекватно работает. в общем, пришли к выводу что на винде при первом запуске копировать приложение во временную папку. |
Сообщ.
#12
,
|
|
|
Короче, дело такое.
Код процесса -- выгружаемая память. И выгружается он не в своп, а просто нафиг. Если что, можно снова с exe-шника подгрузить. Так вот, что в линуксе, что в винде возможна ситуация, что форкнутый процесс полезет на диск за кодом. Но если форк честный и проблем с памятью нет, то диск в общем-то не нужен, и странички памяти могут хоть копиорваться, хоть реюзатся до посинения. Другое дело, что насколько я знаю, в винде форк реализован через тот же CreateProcess (поправьте меня). И он всегда загружает образ с диска (ну либо с кеша файловой системы, хотя сомнительно что все 200 метров останутся в этом самом кеше). |
Сообщ.
#13
,
|
|
|
в винде кэшируется только локальная память, с сетевых источником ничего не кэшируется ибо не гарантируется, что файл не был изменен.
|
Сообщ.
#14
,
|
|
|
Цитата Олег М @ Никакой аналогии там нет. Fork копирует существующий процесс, CreateProcess создает новый, с нуля. Соответственно, требуется загрузка файла Проблема в таргеттинге. Т.е. в семантике. Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса. Вот вам простой пример /*Тут куча инклюдов, опускаем*/ #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() может запустить совершенно новый исполнимый файл, при этом его предыдущее "родительское" содержание в памяти заменяется текстом нового файла. Так что вопрос в семантике форка. Это - не копирование, а разветвление. Потому и говорим, что Винда и никсы обладают совершенно разными подходами к вопросам запуска новых процессов. |
Сообщ.
#15
,
|
|
|
Цитата Oleg2004 @ Форк не копирует родительский процесс, а разветвляет его с созданием нового процесса. Что значит разветвляет? Процесс - это исполняемый код и память, ну и какие-то ресурсы, типа хэндлов. Насколько я понимаю, линукс, в fork() ничего этого не копирует, а просто увеличивает счётчики или типа того. Windows так не умеет. |