На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Обратите внимание:
1. Прежде чем начать новую тему или отправить сообщение, убедитесь, что вы не нарушаете правил форума!
2. Обязательно воспользуйтесь поиском. Возможно, Ваш вопрос уже обсуждали. Полезные ссылки приведены ниже.
3. Темы с просьбой выполнить какую-либо работу за автора в этом разделе не обсуждаются.
4. Используйте теги [ code=cpp ] ...текст программы... [ /code ] для выделения текста программы подсветкой.
5. Помните, здесь телепатов нет. Старайтесь формулировать свой вопрос максимально грамотно и чётко: Как правильно задавать вопросы
6. Запрещено отвечать в темы месячной и более давности без веских на то причин.

Полезные ссылки:
user posted image FAQ Сайта (C++) user posted image FAQ Форума user posted image Наши Исходники user posted image Поиск по Разделу user posted image MSDN Library Online (Windows Driver Kit) user posted image Google

Ваше мнение о модераторах: user posted image B.V.
Модераторы: B.V.
Страницы: (2) 1 [2]  все  ( Перейти к последнему сообщению )  
> Win 10 и ReadFileEx
    nik531
    Я просил весь код, а не одну функцию. Как она вызывается, как инициализируется lpOverlapped перед вызовом. Весь код, который можно скомпилировать и запустить. У меня как раз Win10, могу проверить.
      Цитата Cfon @
      Цитата nik531 @
      разработчик делал всё по документации. Будет любезны поддерживать то что за документировали.

      какой такой документации? документации для какой винды? 10ки? 8?
      и вы будте любезны юзать ее там для какой платформы они ее разработали :whistle:

      Добавлено
      ты вообще читал ее описание? вот почитай
      https://msdn.microsoft.com/ru-ru/library/windows/desktop/aa365468(v=vs.85).aspx

      как раз от туда и цитируем MSDN
      а вот что было обещанно разработчику на момент написания.
      [attach=#0][/attach]
      и тут возникает вопрос. судя по ссылке приведённой вами так эта функция работает на winXP. А судя по скриншоту XP работает не так. либо MS лгали в 2008 году либо лгут сейчас.

      Добавлено
      Цитата Pacific @
      nik531
      Я просил весь код, а не одну функцию. Как она вызывается, как инициализируется lpOverlapped перед вызовом. Весь код, который можно скомпилировать и запустить. У меня как раз Win10, могу проверить.

      К сожалению на тестовом примере повторить поведение не получается. Возможно я что делаю не так как в большом проекте реализовано. А большой проект слишком большой. Состоит больше чем из десятка Dll и десятка lib. Есть конечно большая вероятность что там делается что то не правильно.
      Но MSDN чётко говорит. If ReadFileEx attempts to read past the end-of-file (EOF), the call to GetOverlappedResult for that operation returns FALSE and GetLastError returns ERROR_HANDLE_EOF.
      Что я понимаю как если вы вызвали ReadFileEx для участка файла лежащего за его пределами. GetOverlappedResult должен венуть FALSE и GetLastError returns ERROR_HANDLE_EOF.
      но если поставить точку останова при выполнении этого условия то не стабильно но встречается ситуация когда ReadFileEx вызвано для нулевого смещения и чтать ещё есть чего а результат GetLastError после вызова GetOverlappedResult равен ERROR_HANDLE_EOF;
      Попробую разобраться в чём дело.
      а открывается файл и инциализруется оверлопед струкура такаже как и в тестовом примере в первом посте. чтобы не загружать пост не буду повторять.
      Прикреплённая картинка
      Прикреплённая картинка
        Цитата nik531 @
        К сожалению на тестовом примере повторить поведение не получается. Возможно я что делаю не так как в большом проекте реализовано. А большой проект слишком большой. Состоит больше чем из десятка Dll и десятка lib. Есть конечно большая вероятность что там делается что то не правильно.

        Самая частая ошибка - когда одна и та же структура OVERLAPPED используется одновременно для нескольких разных (одновременных) операций I/O. Например, вызов в цикле ReadFileEx с одной и той же lpOverlapped, не дожидаясь окончания предыдущей операции. В этом случае можно словить самые разные глюки.
          ExpandedWrap disabled
            #include "stdafx.h"
            #include <windows.h>
            #include <stdio.h>
             
            #define BUFSIZE 4096
             
            HANDLE hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
             
            VOID CALLBACK __IOCompletionRoutine( DWORD dwErrorCode, DWORD dwSize, LPOVERLAPPED lpOverlapped )
            {
                //printf("__IOCompletionRoutine(%d)\n", dwErrorCode);
                ::SetEvent(hEvent);
            };
             
            int _tmain(int argc, _TCHAR* argv[])
            {
             
                // Открываем файл
                HANDLE m_hFile = CreateFileW(
                    L"C:\\test.test",
                    GENERIC_READ | GENERIC_WRITE,
                    FILE_SHARE_READ,
                    NULL,
                    OPEN_EXISTING,
                    FILE_ATTRIBUTE_NORMAL |
                        FILE_FLAG_NO_BUFFERING |
                        FILE_FLAG_OVERLAPPED |
                        FILE_FLAG_WRITE_THROUGH |
                        FILE_FLAG_RANDOM_ACCESS,
                    NULL
                );
                
                
                DWORD dwInt = 0;
                byte buffer [BUFSIZE] = {0};    
                OVERLAPPED overloped;
                overloped.hEvent = 0;
                overloped.Internal = 0;
                overloped.InternalHigh = 0;
                overloped.Offset = 0;
                overloped.OffsetHigh = 0;
                for(int i=0;i<10000;i++)
                {
                    dwInt = 0;
                    while(1)
                    {
                        overloped.Offset = dwInt;
                        memset(buffer,0, BUFSIZ);
                        DWORD res = ReadFileEx(m_hFile, buffer, BUFSIZ, &overloped, &__IOCompletionRoutine);
                        DWORD error = GetLastError();
                        if((res == FALSE) && GetLastError() == ERROR_HANDLE_EOF)
                        {
                            printf("break old -%d\n", i);
                            break;
                        }
                    
                        DWORD nBytesRead = 0;
                        if((GetOverlappedResult(m_hFile, &overloped, &nBytesRead, FALSE) == FALSE) && (GetLastError() == ERROR_HANDLE_EOF))
                        {
                            if(overloped.Offset == 0)
                            {
                                    printf("big ass %d\n",i);
                                    printf("overloped.Offset -%d\n", overloped.Offset);
                                    printf("overloped.OffsetHigh -%d\n", overloped.OffsetHigh);
                                    printf("overloped.Internal -%d\n", overloped.Internal);
                                    printf("overloped.InternalHigh -%d\n", overloped.InternalHigh);
                                    printf("overloped.hEvent -%d\n", overloped.hEvent);
                                    printf("overloped.Pointer -%d\n", overloped.Pointer);
                                    Sleep(100000);
                            }
                            printf("break new -%d\n", i);
                            ::WaitForSingleObjectEx( hEvent, INFINITE, TRUE );
                            break;
                        }
                        dwInt += BUFSIZ;
                        ::WaitForSingleObjectEx( hEvent, INFINITE, TRUE );
                    }
                }
                printf("S_OK");
                Sleep(60000);
                return 0;
            }

          вот на этом примере падает, редко когда до тысячи операция чтения проходит
          [attach=#0][/attach]
          не могу добавить файл но 4 кило байта нулей.
          Сообщение отредактировано: nik531 -
            Разобрался. В MSDN про GetOverlappedResult написано:
            Цитата
            If the hEvent member of the OVERLAPPED structure is NULL, the system uses the state of the hFile handle to signal when the operation has been completed. Use of file, named pipe, or communications-device handles for this purpose is discouraged. It is safer to use an event object because of the confusion that can occur when multiple simultaneous overlapped operations are performed on the same file, named pipe, or communications device. In this situation, there is no way to know which operation caused the object's state to be signaled.

            Как раз твой случай. GetOverlappedResult иногда получает результат от предыдущей операции, а не от текущей, так как файловый хэндл у нас один, а операций много в цикле выполняется. Похоже на типичную гонку между двумя потоками: статус у хэндла остался ERROR_HANDLE_EOF от предыдущей операции, код в ядре еще не успел его поменять на STATUS_PENDING, а ты уже его проверяешь, вызывая GetOverlappedResult.

            Исправленный код:
            ExpandedWrap disabled
              #include "stdafx.h"
              #include <windows.h>
              #include <stdio.h>
              #define BUFSIZE 4096
               
              VOID CALLBACK __IOCompletionRoutine(DWORD dwErrorCode, DWORD dwSize, LPOVERLAPPED lpOverlapped)
              {
              }
               
              int _tmain(int argc, _TCHAR* argv[])
              {
                  HANDLE m_hFile = CreateFileW(
                      L"test.test",
                      GENERIC_READ | GENERIC_WRITE,
                      FILE_SHARE_READ,
                      NULL,
                      OPEN_EXISTING,
                      FILE_ATTRIBUTE_NORMAL |
                      FILE_FLAG_NO_BUFFERING |
                      FILE_FLAG_OVERLAPPED |
                      FILE_FLAG_WRITE_THROUGH |
                      FILE_FLAG_RANDOM_ACCESS,
                      NULL
                  );
               
               
                  DWORD dwInt = 0;
               
                  // !!! Важно выделить память под буфер через VirtualAlloc, чтобы она была выровнена для надежной работы с FILE_FLAG_NO_BUFFERING
                  byte* buffer = (byte*) VirtualAlloc(0, BUFSIZE, MEM_COMMIT, PAGE_READWRITE);
                  // !!!
               
                  OVERLAPPED overloped;
                  overloped.hEvent = 0;
                  overloped.Internal = 0;
                  overloped.InternalHigh = 0;
                  overloped.Offset = 0;
                  overloped.OffsetHigh = 0;
                  for (int i = 0; i < 10000; i++)
                  {
                      dwInt = 0;
                      while (1)
                      {
                          overloped.Offset = dwInt;
                          memset(buffer, 0, BUFSIZ);
                          DWORD res = ReadFileEx(m_hFile, buffer, BUFSIZ, &overloped, &__IOCompletionRoutine);
                          if ((res == FALSE) && (GetLastError() == ERROR_HANDLE_EOF))
                          {
                              printf("break old -%d\n", i);
                              break;
                          }
               
                          // !!! SleepEx ставим тут, чтобы точно дождаться завершения текущей операции
                          SleepEx(INFINITE, TRUE);
               
                          DWORD nBytesRead = 0;
                          if ((GetOverlappedResult(m_hFile, &overloped, &nBytesRead, FALSE) == FALSE) && (GetLastError() == ERROR_HANDLE_EOF))
                          {
                              if (overloped.Offset == 0)
                              {
                                  printf("big ass %d\n", i);
                                  printf("overloped.Offset -%d\n", overloped.Offset);
                                  printf("overloped.OffsetHigh -%d\n", overloped.OffsetHigh);
                                  printf("overloped.Internal -%d\n", overloped.Internal);
                                  printf("overloped.InternalHigh -%d\n", overloped.InternalHigh);
                                  printf("overloped.hEvent -%d\n", overloped.hEvent);
                                  printf("overloped.Pointer -%d\n", overloped.Pointer);
                                  Sleep(100000);
                              }
                              break;
                          }
                          dwInt += BUFSIZ;
                      }
                  }
                  printf("S_OK");
                  Sleep(60000);
                  return 0;
              }
              так это получается синхронное чтение тогда.
              И получается нет возможности как раньше узнать достигнут ли конец файла в момент вызова ReadFileEx. И это весьма печальное изменение внесённое корпорацией зла.
              И теперь прейдёться проверять коды ошибок в двух местах. Код ошибки ReadFileEx и код в вызове overloped callback. Что на мой взгляд выглядит как костыли.
              И я правильно понимаю это единственное правильное решение для организации асинхронного чтения файла. И GetOverlappedResult совершенно без полезна в этой ситуации надо всё равно ждать вызова Callback.
                nik531
                Нет, если очень хочется использовать именно GetOverlappedResult, то нужно в lpOverlapped прописать hEvent. Для каждой отдельной lpOverlapped - свой hEvent. Но надежнее ждать именно IOCompletionRoutine, и там выставлять свой флаг "можно запускать следующую операцию".

                Добавлено
                Я бы вообще использовал IOCP - https://msdn.microsoft.com/en-us/library/wi...8(v=vs.85).aspx
                GetQueuedCompletionStatus работает надёжно.
                  Цитата nik531 @
                  И это весьма печальное изменение внесённое корпорацией зла.

                  сам ты зло, руки выпрями сначала, а потом бросай критику того чего ты даже близко не понимаешь :D
                  Сообщение отредактировано: Cfon -
                    Цитата Cfon @
                    сам ты зло, руки выпрями сначала, а потом бросай критику того чего ты даже близко не понимаешь

                    если базовая функция такая как работа с файлом меняет свое поведение в новой версии ОС это зло. А корпорация которая это делает корпорация зла. что тут сложного ?
                    при чём тут руки.
                    Сообщение отредактировано: nik531 -
                      Цитата nik531 @
                      если базовая функция такая как работа с файлом меняет свое поведение в новой версии ОС это зло. А корпорация которая это делает корпорация зла. что тут сложного ?
                      при чём тут руки.

                      значит надо выпрямить руки сотрудникам Мелкософта так? :D

                      Добавлено
                      хотя скорее ты прав там же индусы работают с кривыми руками :D
                      Сообщение отредактировано: Cfon -
                        Цитата nik531 @
                        И получается нет возможности как раньше узнать достигнут ли конец файла в момент вызова ReadFileEx.
                        И теперь прейдёться проверять коды ошибок в двух местах.

                        Может проще делать проверку самому до вызова ReadFileEx? Всё равно же Offset для чтения "ручками" задаешь - что мешает добавить сравнение с GetFileSize?
                          Цитата leo @
                          Может проще делать проверку самому до вызова ReadFileEx? Всё равно же Offset для чтения "ручками" задаешь - что мешает добавить сравнение с GetFileSize?

                          Мне кажется это замедлит работу. А быстро действие в этом проекте критично.
                            nik531
                            У вас какое-то странное представление о быстродействии. Проверка "if (offset < size)" в миллион раз быстрее, чем чтение данных с диска (обычного, HDD). Уж если работа с диском так критична, то проще вложиться в какой-нибудь SSD для PCI-Express слота, который точно позволит упереться в CPU. А потом только оптимизировать код чтения файла.
                              Цитата nik531 @
                              Мне кажется это замедлит работу

                              Если размер файла при чтении не изменяется, то GetFileSize достаточно вызвать 1 раз. Соотв-но, затраты времени на этот вызов будут мизерными по сравнению с открытием и чтением самого файла.
                                Файл может меняться между процедурами чтения файла. GetSize на сколько я понимаю приведёт к обращенbю к HDD. Я кончно не замерял. но что мешает корпарции зла сделать такую подляну в будущих версиях. Пока работает так отсавлю. Если кто проверит на сколько быстро выполнятся GetFileEx. Буду благодарен. А файл там большие до 20 гигобайт. и читаются блоками о 512 кило байт.
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0664 ]   [ 18 queries used ]   [ Generated: 7.05.24, 09:28 GMT ]