2009-06-26 4 views
9

Я знаю, что в C++ есть функция is_open(), но я хочу, чтобы одна программа проверяла, не открылся ли файл другим приложением. Есть ли способ сделать это, используя стандартную библиотеку?Как проверить, был ли файл открыт другим приложением на C++?

EDIT - Уточнено в ответах, что это касается приложения Linux.

ответ

4

Нет, стандартная библиотека не имеет такой функциональности.

0

Non-нативно, можно взывать к Sysinternals' handle.exe в крайнем случае ...

+0

+1 Я искал приложение, которое делает именно то, что делает handle.exe. Спасибо ZombieSheep. – Kei

1

Может быть, вы могли бы просто попытаться получить полную блокировку записи? Это не удастся, если кто-нибудь еще откроет для чтения или записи.

fopen("myfile.txt", "r+") 

Если это не кросс-платформенный и Win32, то вы можете запросить еще более мелкозернистый набор замков.

См. here и посмотрите dwShareMode, значение 0, а также другие параметры.

+0

Полностью зависит от операционной системы. – 2009-06-26 11:39:12

0

Как @Neil Butterworth говорит, стандартная библиотека не делает.

В unix вы можете использовать fcntl, чтобы использовать блокировки файлов.

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

+0

Блокировка является чисто консультативной, поэтому это только говорит вам, если кто-то еще собрал файл. – ephemient

0

В этом окошек и грязный трюк будет работать (если файл существует и у вас есть права доступа)

if ( 0 != rename("c:/foo.txt", "c:/foo.txt") ) { 
    printf("already opened\n"); 
    } 

Это, скорее всего, работать и в Linux.

+0

Это действительно грязно :-) – Totonga

+0

:) –

+0

Я мог легко представить, что кто-то добавит «исправление» в os в будущем, что сломает этот трюк. – Brian

3

Не только стандартная библиотека не обладает этой функциональностью, но и вообще невозможна. Вы можете (по linux) проверить /proc/*/fd —, но возможно, что ваша программа не имеет разрешения на выполнение процессов от других пользователей (например, по умолчанию это относится к Ubuntu).

2

Если вы контролируете другой процесс (есть исходный код), лучшим планом является использование консультативных блокировок в обоих процессах. Эта блокировка определена в POSIX и будет переносимой в разных операционных системах.

В Linux вы можете использовать служебную программу lsof, чтобы узнать, какие файлы открываются другими процессами.

Это ограничение ограничено тем, что у вас есть разрешения - вы должны сделать чек в качестве привилегированного пользователя или получить результаты только для файлов, открытых тем же пользователем, что и тот, который делает чек.

Я знаю только об утилите командной строки, а не о любом системном вызове, который вы можете использовать непосредственно из кода C.

В Linux также можно включить mandatory locking для данной файловой системы (mount -o mand) и установить специальные флаги в файле (chmod g-x, g + s). Затем, когда ваш процесс пытается получить блокировку записи, он не будет работать, если другой процесс откроет файл. Это вряд ли когда-либо используется, но если вы полностью контролируете рассматриваемую систему, это может быть вариант.

+1

Я пробовал смотреть на исходный код lsof один раз, чтобы посмотреть, как они это сделали, и моя голова чуть не взорвалась. Источником lsof является сеть безумия и черной магии. –

+2

Я бы предложил использовать фьюзер над lsof. Разбор результатов будет намного проще. – AFoglia

2

Этот код может работать.

int main(int argc, char ** argv) 
{ 
    int fd = open(argv[1], O_RDONLY); 
    if (fd < 0) { 
     perror("open"); 
     return 1; 
    } 

    if (fcntl(fd, F_SETLEASE, F_WRLCK) && EAGAIN == errno) { 
     puts("file has been opened"); 
    } 
    else { 
     fcntl(fd, F_SETLEASE, F_UNLCK); 
     puts("file has not been opened"); 
    } 

    close(fd); 
    return 0; 
}