Как Вы делаете не блокирующуюся консоль I/O on Linux in C?

Кто-то слышал, что эти серые линии на самом деле не выполняются

blockquote>

Потому что вы смотрите на адаптивный план - и ваш «кто-то» прав.

Другими словами, Oracle создает план выполнения для вашего запроса ... начинает его выполнять, начинает замечать, что все идет не так, как ожидалось, и на лету вносит исправления в курс.

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

В вашем плане есть элемент для сбора статистики в вашей таблице - оптимизатор просмотрел данные, относящиеся к предикатам этого запроса (диапазон дат), и число строк, указанных в статистике, равно WAAAY. выкл, так что в этот момент оптимизатор говорит, что мы идем другим путем.

Это новая функция для базы данных 12c, вы пометили Oracle11g, но этот план говорит нам, что мы находимся на 12.

Если вы немного прокрутите свой план в SQL Developer, вы увидите, что база данных сообщает вам, что функция адаптивного плана находится в игре

enter image description here

32
задан Flimm 29 November 2012 в 21:17
поделиться

7 ответов

Вы не делаете, действительно. TTY (консоль) является довольно ограниченным устройством, и Вы в значительной степени не делаете не блокирующегося ввода-вывода. То, что Вы делаете, когда Вы видите что-то, что похоже на неблокирование ввода-вывода, скажите в curses/ncurses приложении, называют необработанным вводом-выводом. В необработанном вводе-выводе нет никакой интерпретации символов, никакого стирания, обрабатывающего и т.д. Вместо этого необходимо написать собственный код, который проверяет на данные при выполнении других вещей.

В современных программах C можно упростить это иначе путем помещения консоли I/O в поток или легкий процесс. Затем ввод-вывод может продолжиться обычным способом блокирования, но данные могут быть вставлены в очередь, чтобы быть обработанными на другом потоке.

Обновление

Вот учебное руководство по проклятиям, которое касается его больше.

9
ответ дан 27 November 2019 в 20:35
поделиться
4
ответ дан 27 November 2019 в 20:35
поделиться

Я отметил "Не блокирующийся ввод данных пользователем в цикле без ncurses" ранее в этом месяце, когда я думал, что мне, возможно, понадобилось бы неблокирование, небуферизованный консольный вход, но я не сделал, так не может ручаться за то, работает ли это или нет. Для моего использования я не заботился, что это не стало введенным, пока пользовательский хит не входит, поэтому просто использовал aio для чтения stdin.

6
ответ дан 27 November 2019 в 20:35
поделиться

используйте ncurses

3
ответ дан 27 November 2019 в 20:35
поделиться

Не совсем уверенный, что Вы подразумеваете под 'консолью IO' - Вы читаете из STDIN, или действительно ли это - консольное приложение, которое читает из некоторого другого источника?

Если Вы будете читать из STDIN, то необходимо будет пропустить освобожденный () и использовать чтение () и запись () с опросом () или выбор (), чтобы помешать вызовам блокироваться. Вы можете отключать буферизацию ввода, которая должна заставить освобожденный возвращать EOF с setbuf (), но я никогда не пробовал его.

0
ответ дан 27 November 2019 в 20:35
поделиться

Как и Пит Киркхэм , я нашел cc.byexamples.com , и у меня это сработало. Перейдите туда, чтобы получить хорошее объяснение проблемы, а также версию ncurses.

Моему коду нужно было принять начальную команду из стандартного ввода или файла, а затем следить за командой отмены во время обработки начальной команды. Мой код - C ++, но вы должны иметь возможность использовать scanf () и все остальное, где я использую функцию ввода C ++ getline ().

Мясо - это функция, которая проверяет, доступен ли какой-либо ввод:

#include <unistd.h>
#include <stdio.h>
#include <sys/select.h>

// cc.byexamples.com calls this int kbhit(), to mirror the Windows console
//  function of the same name.  Otherwise, the code is the same.
bool inputAvailable()  
{
  struct timeval tv;
  fd_set fds;
  tv.tv_sec = 0;
  tv.tv_usec = 0;
  FD_ZERO(&fds);
  FD_SET(STDIN_FILENO, &fds);
  select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
  return (FD_ISSET(0, &fds));
}

Это должен вызываться перед любой функцией ввода stdin. Когда я использовал std :: cin перед использованием этой функции, он больше никогда не возвращал true. Например, main () имеет цикл, который выглядит следующим образом:

int main(int argc, char* argv[])
{ 
   std::string initialCommand;
   if (argc > 1) {
      // Code to get the initial command from a file
   } else {
     while (!inputAvailable()) {
       std::cout << "Waiting for input (Ctrl-C to cancel)..." << std::endl;
       sleep(1);
     }
     std::getline(std::cin, initialCommand);
   }

   // Start a thread class instance 'jobThread' to run the command
   // Start a thread class instance 'inputThread' to look for further commands
   return 0;
}

Во входном потоке новые команды были добавлены в очередь, которая периодически обрабатывалась jobThread. InputThread выглядел примерно так:

THREAD_RETURN inputThread()
{
  while( !cancelled() ) {
    if (inputAvailable()) {
      std::string nextCommand;
      getline(std::cin, nextCommand);
      commandQueue.lock();
      commandQueue.add(nextCommand);
      commandQueue.unlock();
    } else {
        sleep(1);
    }
  }
  return 0;
}

Эта функция, вероятно, могла быть в main (), но я работаю с существующей базой кода, а не против нее.

Для моей системы входные данные не были доступны до тех пор, пока новая строка была отправлена, что я и хотел. Если вы хотите читать каждый символ при вводе, вам нужно отключить «канонический режим» на стандартном вводе. cc.byexamples.com содержит несколько предложений, которые я не пробовал, но остальные сработали, так что они должны работать.

на стандартном вводе. cc.byexamples.com содержит несколько предложений, которые я не пробовал, но остальные сработали, так что они должны работать.

на стандартном вводе. cc.byexamples.com содержит несколько предложений, которые я не пробовал, но остальные сработали, так что они должны работать.

19
ответ дан 27 November 2019 в 20:35
поделиться

Другой альтернативой использованию ncurses или потоков является использование GNU Readline , в частности его часть, которая позволяет вам регистрировать функции обратного вызова . Шаблон следующий:

  1. Используйте select () на STDIN (среди любых других дескрипторов)
  2. Когда select () сообщает вам, что STDIN готов к чтению, вызовите rl_callback_read_char () readline
  3. Если пользователь ввел полная строка, rl_callback_read_char вызовет ваш обратный вызов. В противном случае он вернется немедленно, и ваш другой код может продолжиться.
2
ответ дан 27 November 2019 в 20:35
поделиться
Другие вопросы по тегам:

Похожие вопросы: