5

Я просто писал программу на C++ на моем компьютере с Ubuntu 14.10. Поскольку это клиент-серверная программа, у меня открыто три эмулятора терминала: один для написания кода и компиляции, один для тестирования клиента и последний для тестирования сервера. Через некоторое время я подумал, что в моем коде есть ошибка. Я потерял более часа, выслеживая его, и оказалось, что выход из каталога и повторный вход в него решили всю проблему. Чтобы быть точным, это были команды, которые я выполнил:

some_directory$ ./client
some_directory$ cd ..
$ cd some_directory
some_directory$ ./client

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

2 ответа2

3

Я не думаю, что bash делает что-то необычное (он кеширует пути к исполняемым файлам, указанным без путей, но здесь это неприменимо, так как вы указываете путь)

Похоже, каталог, в котором вы были, был перемещен или смонтирован. В случае создания программного обеспечения, перемещение каталога более вероятно.

Случай перемещения каталога

Пример воссоздания поведения перемещения каталога в терминале 1

cd /tmp
mkdir dir1
cd dir1
touch exampleFile

Затем в терминале 2:

cd /tmp
mv dir1 dir2
mkdir dir1
cd dir1

Обе оболочки отображаются как находящиеся в каталоге с именем 'dir1', но список будет отображать различное содержимое. Если терминал2 создает файл с именем «exampleFile», обе оболочки будут показывать «exampleFile» в «dir1», но это разные файлы. Это потому, что оболочка в терминале 1 фактически находится в dir2, она просто не знает об этом. Оболочка в терминале 1 может добраться до реального dir1 через cd:

cd .

Это выглядит странно, но заново разрешает путь.

Над креплением

Это происходит, когда оболочка (или любая программа) находится в каталоге, а затем над ним монтируется файловая система. Например, в терминале 1:

mkdir /tmp/dir1
cd /tmp/dir1

терминал 2:

mount /dev/whateverdev /tmp/dir1
cd /tmp/dir1

Терминал 1 видит файлы из исходной файловой системы в этом каталоге. Терминал 2 видит файлы из /dev / whatdev.

Как избежать

В случае перемонтирования, это в основном просто осведомленность о том, что вы делаете или как настроена ваша машина (например, если автомонтирование работает, когда подключен USB-накопитель).

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

Конечно, это также мог быть случайный случайный несчастный случай (аналогичный тому, что был показан в первом примере выше). В этом случае, понимание того, что это может произойти, поможет вам.

2

В общем hash и sync

hash - встроенная команда bash

Для ускорения операции при выполнении команды оболочка bash сохраняет свой путь в хеш-таблице. Каждый экземпляр shell имеет свою собственную hash table . Для получения дополнительной информации прочитайте этот отрывок из man bash:

Если имя не является ни функцией оболочки, ни встроенной функцией и не содержит косых черт, bash ищет в каждом элементе PATH каталог, содержащий исполняемый файл с этим именем.
Bash использует хеш-таблицу для запоминания полных путей исполняемых файлов (см. hash под разделом «Команды SHELL BUILTIN» ниже). Полный поиск по каталогам в PATH выполняется только в том случае, если команда не найдена в хэш-таблице.

Вы можете заменить запись в списке (например, client команды) hash client ; Вы можете удалить эту запись из списка с помощью hash -d client ; Вы можете полностью сбросить список с помощью hash -r .

Sync - синхронизировать данные на диске с памятью

Команда sync гарантирует, что все в памяти будет записано на диск.

Для ускорения работы часто Linux может хранить некоторые данные в буферах файловой системы ядра, то есть данные, которые были запланированы для записи с помощью системных вызовов низкоуровневого ввода-вывода [1].

С другой стороны, «жесткие диски могут по умолчанию использовать свой собственный энергозависимый кэш записи для буферизации записи, что значительно повышает производительность, в то же время создавая потенциал для потерянных записей» [2]

sync записывает любые данные, буферизованные в памяти, на диск. Это может включать (но не ограничиваясь этим) модифицированные суперблоки, модифицированные inode и отложенные операции чтения и записи. Это должно быть реализовано ядром; Программа sync выполняет только системный вызов sync. Ядро хранит данные в памяти, чтобы избежать (относительно медленного) чтения и записи на диск. Это улучшает производительность, но ...

[если вы заинтересованы, продолжайте читать здесь или с info coreutils sync ].

Специфично для вашей проблемы

Если ваша проблема зависит от одного из вышеперечисленных аспектов, вы можете попытаться написать в одной строке более одной команды, и после быстрого вызова их с помощью клавиши со стрелкой вверх, например:

  • hash -d ./client; ./client ,
  • sync ; ./client ,
  • hash -d ./client ; sync ; ./client
  • (cd .. ; cd - ; ./client ) , ваше собственное решение. Здесь вы выполняете клиент в подоболочке, которая наследует все, что вы сделали в своей оболочке (как переменные ...), но не возвращает изменений в текущую оболочку.

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .