стандартное поведение ОС при доступе к файлам?
От: Amouse Россия  
Дата: 12.10.06 14:44
Оценка:
как ведут себя Windows и Linux при множественном доступе к обычным файлам?
если скажем одна программа захочет записать в файл, вторая тоже записать, третья прочитать?
Re: стандартное поведение ОС при доступе к файлам?
От: koandrew Канада http://thingselectronic.blogspot.ca/
Дата: 12.10.06 16:16
Оценка:
Здравствуйте, Amouse, Вы писали:

A>как ведут себя Windows и Linux при множественном доступе к обычным файлам?

A>если скажем одна программа захочет записать в файл, вторая тоже записать, третья прочитать?

RTFM
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
[КУ] оккупировала армия.
Re: стандартное поведение ОС при доступе к файлам?
От: MaximE Великобритания  
Дата: 12.10.06 20:09
Оценка: 3 (2)
Amouse wrote:

> как ведут себя Windows и Linux при множественном доступе к обычным файлам?

> если скажем одна программа захочет записать в файл, вторая тоже
> записать, третья прочитать?

На Линукс с read/write() все просто.

В ядре файл представлен структурой inode.
http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L539 В струтуре
есть mutex, который сериализует доступ к ней. Соответственно, процессы будут
выполнять read()/write() по очереди. В случае, когда файл находится не в
локальной файловой системе, а где-то на nfs, доступ к этой структуре
сериализуется операционной системой хоста, на локальной файловой системе
которого этот файл находится.

Получит ли твои процессы кашу или корректные данные, зависит от характера данных
файла и протокола доступа (concurrency control).

Для обеспечения протокола корректного доступа эти процессы могут использовать
файловые блокировки.

http://www.opengroup.org/onlinepubs/009695399/functions/fcntl.html

This volume of IEEE Std 1003.1-2001 permits concurrent read and write
access to file data using the fcntl() function; this is a change from the 1984
/usr/group standard and early proposals. Without concurrency controls, this
feature may not be fully utilized without occasional loss of data.

Data losses occur in several ways. One case occurs when several processes
try to update the same record, without sequencing controls; several updates may
occur in parallel and the last writer "wins". Another case is a bit-tree or
other internal list-based database that is undergoing reorganization. Without
exclusive use to the tree segment by the updating process, other reading
processes chance getting lost in the database when the index blocks are split,
condensed, inserted, or deleted. While fcntl() is useful for many applications,
it is not intended to be overly general and does not handle the bit-tree example
well.

This facility is only required for regular files because it is not
appropriate for many devices such as terminals and network connections.

Since fcntl() works with "any file descriptor associated with that file,
however it is obtained", the file descriptor may have been inherited through a
fork() or exec operation and thus may affect a file that another process also
has open.

The use of the open file description to identify what to lock requires
extra calls and presents problems if several processes are sharing an open file
description, but there are too many implementations of the existing mechanism
for this volume of IEEE Std 1003.1-2001 to use different specifications.

Another consequence of this model is that closing any file descriptor for a
given file (whether or not it is the same open file description that created the
lock) causes the locks on that file to be relinquished for that process.
Equivalently, any close for any file/process pair relinquishes the locks owned
on that file for that process. But note that while an open file description may
be shared through fork(), locks are not inherited through fork(). Yet locks may
be inherited through one of the exec functions.

The identification of a machine in a network environment is outside the
scope of this volume of IEEE Std 1003.1-2001. Thus, an l_sysid member, such as
found in System V, is not included in the locking structure.

Changing of lock types can result in a previously locked region being split
into smaller regions.

Mandatory locking was a major feature of the 1984 /usr/group standard.

For advisory file record locking to be effective, all processes that have
access to a file must cooperate and use the advisory mechanism before doing I/O
on the file. Enforcement-mode record locking is important when it cannot be
assumed that all processes are cooperating. For example, if one user uses an
editor to update a file at the same time that a second user executes another
process that updates the same file and if only one of the two processes is using
advisory locking, the processes are not cooperating. Enforcement-mode record
locking would protect against accidental collisions.

Secondly, advisory record locking requires a process using locking to
bracket each I/O operation with lock (or test) and unlock operations. With
enforcement-mode file and record locking, a process can lock the file once and
unlock when all I/O operations have been completed. Enforcement-mode record
locking provides a base that can be enhanced; for example, with sharable locks.
That is, the mechanism could be enhanced to allow a process to lock a file so
other processes could read it, but none of them could write it.

Mandatory locks were omitted for several reasons:

1.

Mandatory lock setting was done by multiplexing the set-group-ID bit
in most implementations; this was confusing, at best.
2.

The relationship to file truncation as supported in 4.2 BSD was not
well specified.
3.

Any publicly readable file could be locked by anyone. Many historical
implementations keep the password database in a publicly readable file. A
malicious user could thus prohibit logins. Another possibility would be to hold
open a long-distance telephone line.
4.

Some demand-paged historical implementations offer memory mapped
files, and enforcement cannot be done on that type of file.

Since sleeping on a region is interrupted with any signal, alarm() may be
used to provide a timeout facility in applications requiring it. This is useful
in deadlock detection. Since implementation of full deadlock detection is not
always feasible, the [EDEADLK] error was made optional.


--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[2]: стандартное поведение ОС при доступе к файлам?
От: Amouse Россия  
Дата: 13.10.06 15:57
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>На Линукс с read/write() все просто.


ME>В ядре файл представлен структурой inode.

ME>http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L539 В струтуре
ME>есть mutex, который сериализует доступ к ней. Соответственно, процессы будут


очень интересно.

т.е. инод представляет собой отображение файла. И он соответственно в ядре в единственном числе.
Но тогда такие вопросы.
Скажем, если мы делаем доступ к файлу (пусть для простоты к обычному файлу и только для чтения) из разных процессов
id1 = open('file.txt'..); // в процессе №1
id2 = open('file.txt'..); // в процессе №2
..
идентификатор файла будет один и тот же во всех случаях, так?
Как будет разруливаться, скажем, работа с указателем на данные в файле (тот, который работает с seek/tell)?
Он получается тоже один для всех процессов? Правда в иноде я этого указателя не вижу, но тогда другой вопрос —
а где он находится?

И вот еще такое понятие, как "текущий каталог" (свой для каждого процесса).
По идее он должен быть достаточно тесно связано с файловой системой,
так как может значительно ускорить поиск файла, с которым надо работать (если путь задан от текущего каталога).
Т.е. при открытии файла, этот параметр должен где-то "подхватываться". Тоже непонятно как и где.
Re[3]: стандартное поведение ОС при доступе к файлам?
От: MaximE Великобритания  
Дата: 13.10.06 18:27
Оценка: 4 (2)
Amouse wrote:

> ME>На Линукс с read/write() все просто.

>
> ME>В ядре файл представлен структурой inode.
> ME>http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L539 В
> струтуре
> ME>есть mutex, который сериализует доступ к ней. Соответственно,
> процессы будут
>
> очень интересно.
>
> т.е. инод представляет собой отображение файла.

Да, inode — это id файла. Заметь, что у файла может быть несколько имен (hard
links). Имя файла или папки, что, на unix часто (ext2/3fs) просто специальный
файл, представлено структурой dentry
http://www.linux-m32r.org/lxr/http/source/include/linux/dcache.h#L82 Несколько
dentry, в случае нескольких hard link'ов, ссылаются на один и тот же inode.

Мне очень по душе это разделение: данные и метаданные (size, atime, mtime,
ctime, ...) — одна сущность, имена — другая.

> И он соответственно в ядре в единственном числе.


Верно.

> Но тогда такие вопросы.

> Скажем, если мы делаем доступ к файлу (пусть для простоты к обычному
> файлу и только для чтения) из разных процессов
> id1 = open('file.txt'..); // в процессе №1
> id2 = open('file.txt'..); // в процессе №2
> ..
> идентификатор файла будет один и тот же во всех случаях, так?

Так. Файл один и тот же, представлен единственным inode в ядре.

> Как будет разруливаться, скажем, работа с указателем на данные в файле

> (тот, который работает с seek/tell)?
> Он получается тоже один для всех процессов?
> Правда в иноде я этого
> указателя не вижу, но тогда другой вопрос —
> а где он находится?

Для процесса файл представлен копией структуры file.
http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L713

Из кода видно, что в этой структуре хранится f_pos. Отфоркнутый процесс получает
собственную копию этой структуры, т.е. f_pos у parent и child свои. file
ссылается на dentry, dentry на inode. Стр-ра процесса task_struct включает
files_struct, которая включает fdtable.
http://www.linux-m32r.org/lxr/http/source/include/linux/file.h#L34

Дескриптор файла fd в user space — это просто индекс в массиве struct file** fd
в fdtable.

> И вот еще такое понятие, как "текущий каталог" (свой для каждого процесса).

> По идее он должен быть достаточно тесно связано с файловой системой,

Так.

> так как может значительно ускорить поиск файла, с которым надо работать

> (если путь задан от текущего каталога).
> Т.е. при открытии файла, этот параметр должен где-то "подхватываться".
> Тоже непонятно как и где.

Этим занимается ф-ция do_path_lookup() в строке 1134.
http://www.linux-m32r.org/lxr/http/source/fs/namei.c#L1105 Ты легко найдешь эту
ф-цию, следуя вызовам в sys_open.

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[4]: стандартное поведение ОС при доступе к файлам?
От: MaximE Великобритания  
Дата: 13.10.06 19:24
Оценка: 3 (1)
MaximE wrote:

[]

Пару Linux-specific поведений:



dentry кэшируются.

Это означает, что после того, как они были считаны с диска, они помещаются в
кэш. При последующем обращении к dentry, если она найдена в кэше к диску не
обращаются. Это хорошо видно на примере с find:

$ free
              total       used       free     shared    buffers     cached
Mem:       3994624    3146472     848152          0     233448    2382840
-/+ buffers/cache:     530184    3464440
Swap:     15358132         32   15358100

$ time find /usr -name set
/usr/include/boost/mpl/set
/usr/include/c++/3.3.4/set
/usr/include/c++/3.2.3/set
/usr/include/c++/4.1.1/debug/set
/usr/include/c++/4.1.1/set

real    0m15.227s
user    0m0.180s
sys    0m0.616s

$ free
              total       used       free     shared    buffers     cached
Mem:       3994624    3174716     819908          0     260512    2382348
-/+ buffers/cache:     531856    3462768
Swap:     15358132         32   15358100

$ time find /usr -name map
/usr/include/boost/mpl/map
/usr/include/c++/3.3.4/map
/usr/include/c++/3.2.3/map
/usr/include/c++/4.1.1/debug/map
/usr/include/c++/4.1.1/map
/usr/share/texmf-var/fonts/map

real    0m0.647s
user    0m0.112s
sys    0m0.512s

$ free
              total       used       free     shared    buffers     cached
Mem:       3994624    3174852     819772          0     260516    2382344
-/+ buffers/cache:     531992    3462632
Swap:     15358132         32   15358100


Первый поиск занял 15 секунд и увеличил размер кэша файловой системы на 27mb.
Второй поиск с той же начальной папки занял меньше секунды и увеличил размер
кэша на 4kb.




Обычный write() не пишет данные на диск. Изменения сохраняются в буфере файла а
памяти. Они записываются на диск демоном pdflush в ядре, после истеченеия
таймаута или когда memory pressure. read() всегда возаращает данные из этого
кэша, если они в кэше, либо зачитывает диск и помещает данные в кэш.

При помощи laptop-mode можно настроить таймауты сбрасывания данных на диск так,
что диск твоего ноутбука, при редактировании файлов и компиляции в самолете,
будет включаться и раскручиваться раз в 10 — сколько-по-душе минут. +1 час
работы от батареи. winodoze такое не снилось.




Иногда мелькает вопрос, как из fd достать имя файла. Это технически легко
возможно в Linux, т.к. file ссылается на dentry, последнее есть имя файла
(точнее узел path, из которого можно дойти до /). Системный вызов для этого не
создан, видимо, для того, чтобы не конфузить юзеров этого вызова потому, что не
каждый fd есть файл в файловой системе.

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[5]: стандартное поведение ОС при доступе к файлам?
От: nau  
Дата: 14.10.06 14:08
Оценка:
Здравствуйте, MaximE, Вы писали:

ME>При помощи laptop-mode можно настроить таймауты сбрасывания данных на диск так,

ME>что диск твоего ноутбука, при редактировании файлов и компиляции в самолете,
ME>будет включаться и раскручиваться раз в 10 — сколько-по-душе минут. +1 час
ME>работы от батареи. winodoze такое не снилось.
Очень интересно. Вы не могли бы рассказать подробнее о тюнинге Linux на ноутбуке для увеличения времени работы от батареи? Гугл и т.д. безусловно поможет, но если здесь, на русском, вами — я думаю это сэкономит массу времени многим людям.
В теории практика не отличается от теории, но на практике — отличается
Re[6]: стандартное поведение ОС при доступе к файлам?
От: Cyberax Марс  
Дата: 14.10.06 14:37
Оценка: 13 (1)
nau wrote:
> Очень интересно. Вы не могли бы рассказать подробнее о тюнинге Linux на
> ноутбуке для увеличения времени работы от батареи? Гугл и т.д.
> безусловно поможет, но если здесь, на русском, вами — я думаю это
> сэкономит массу времени многим людям.
Ну, у меня все было просто "apt-get install laptop-mode-tools" и затем
редактируем конфиг. Прямо в конфиге находятся описания нужных опций, там
достаточно просто разобраться. Я поставил задержку сброса в 15 минут.

В результате, при нормальной работе от батарейки (то есть если не
запускать find по всему диску) время ее жизни увеличивается на 25%.

Из тонкостей — настроить используемые программы так, чтобы они
расходовали как можно меньше памяти. Особенно это касается программ на
Java и сложных метапрограмм на С++
Posted via RSDN NNTP Server 2.0
Sapienti sat!
Re[4]: стандартное поведение ОС при доступе к файлам?
От: Amouse Россия  
Дата: 16.10.06 09:16
Оценка:
Здравствуйте, MaximE, Вы писали:

>> Но тогда такие вопросы.

>> Скажем, если мы делаем доступ к файлу (пусть для простоты к обычному
>> файлу и только для чтения) из разных процессов
>> id1 = open('file.txt'..); // в процессе №1
>> id2 = open('file.txt'..); // в процессе №2
>> ..
>> идентификатор файла будет один и тот же во всех случаях, так?

ME>Так. Файл один и тот же, представлен единственным inode в ядре.



хм, а вот в виндах,
id1 = open('file.txt'..);
id2 = open('file.txt'..);

id1 != id2
даже в одном процессе...
Re[5]: стандартное поведение ОС при доступе к файлам?
От: nau  
Дата: 16.10.06 12:22
Оценка:
Здравствуйте, Amouse, Вы писали:

ME>>Так. Файл один и тот же, представлен единственным inode в ядре.


A>хм, а вот в виндах,

A>
A>id1 = open('file.txt'..);
A>id2 = open('file.txt'..);
A>

A>id1 != id2
A>даже в одном процессе...
Функция open возвращает файловый дескриптор, это не inode файла. Где-то в ядерных структурах (как звучит, а!) эти дескрипторы "ссылаются" на один и тот же инод.
В теории практика не отличается от теории, но на практике — отличается
Re[5]: стандартное поведение ОС при доступе к файлам?
От: MaximE Великобритания  
Дата: 16.10.06 13:24
Оценка:
Amouse wrote:

> Здравствуйте, MaximE, Вы писали:

>
>> > Но тогда такие вопросы.
>> > Скажем, если мы делаем доступ к файлу (пусть для простоты к обычному
>> > файлу и только для чтения) из разных процессов
>> > id1 = open('file.txt'..); // в процессе №1
>> > id2 = open('file.txt'..); // в процессе №2
>> > ..
>> > идентификатор файла будет один и тот же во всех случаях, так?
>
> ME>Так. Файл один и тот же, представлен единственным inode в ядре.
>
>
> хм, а вот в виндах,
>
> id1 = open('file.txt'..);
> id2 = open('file.txt'..);
> 
> 
> id1 != id2

> даже в одном процессе...

В linux то же самое. Под id я имел ввиду identity файла — inode.

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
Re[4]: стандартное поведение ОС при доступе к файлам?
От: Amouse Россия  
Дата: 19.10.06 13:11
Оценка:
Здравствуйте, MaximE, Вы писали:

>> Как будет разруливаться, скажем, работа с указателем на данные в файле

>> (тот, который работает с seek/tell)?
>> Он получается тоже один для всех процессов?
>> Правда в иноде я этого
>> указателя не вижу, но тогда другой вопрос —
>> а где он находится?

ME>Для процесса файл представлен копией структуры file.

ME>http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L713

ME>Из кода видно, что в этой структуре хранится f_pos. Отфоркнутый процесс получает

ME>собственную копию этой структуры, т.е. f_pos у parent и child свои. file
ME>ссылается на dentry, dentry на inode. Стр-ра процесса task_struct включает
ME>files_struct, которая включает fdtable.
ME>http://www.linux-m32r.org/lxr/http/source/include/linux/file.h#L34

такая тонкость.
Каждый новый процесс получает копию стр-ры file, но в одном процессе (программе) мы можем сделать

id1 = open("a1",..);
id2 = open("a1",..);

при этом id будут разные, т.е. еще и в рамках одного процесса идет "размножение" стр-ры при каждом открытии файла?
Re[2]: стандартное поведение ОС при доступе к файлам?
От: Аноним  
Дата: 20.10.06 07:58
Оценка:
ME>На Линукс с read/write() все просто.

ME>В ядре файл представлен структурой inode.

ME>http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L539 В струтуре
ME>есть mutex, который сериализует доступ к ней. Соответственно, процессы будут
ME>выполнять read()/write() по очереди.

Блин, не может всё быть так отстойно!
Почему параллельные записи в начало и конец файла должны ждать друг друга?

Может mutex'ом закрыт доступ к самой структуре а не к опрациям чтения/записи?
Re[5]: стандартное поведение ОС при доступе к файлам?
От: MaximE Великобритания  
Дата: 20.10.06 13:26
Оценка: 2 (1)
Здравствуйте, Amouse, Вы писали:

A>Здравствуйте, MaximE, Вы писали:


>>> Как будет разруливаться, скажем, работа с указателем на данные в файле

>>> (тот, который работает с seek/tell)?
>>> Он получается тоже один для всех процессов?
>>> Правда в иноде я этого
>>> указателя не вижу, но тогда другой вопрос —
>>> а где он находится?

ME>>Для процесса файл представлен копией структуры file.

ME>>http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L713

ME>>Из кода видно, что в этой структуре хранится f_pos. Отфоркнутый процесс получает

ME>>собственную копию этой структуры, т.е. f_pos у parent и child свои. file
ME>>ссылается на dentry, dentry на inode. Стр-ра процесса task_struct включает
ME>>files_struct, которая включает fdtable.
ME>>http://www.linux-m32r.org/lxr/http/source/include/linux/file.h#L34

A>такая тонкость.

A>Каждый новый процесс получает копию стр-ры file, но в одном процессе (программе) мы можем сделать

A>id1 = open("a1",..);

A>id2 = open("a1",..);

A>при этом id будут разные, т.е. еще и в рамках одного процесса идет "размножение" стр-ры при каждом открытии файла?


Так. Еще ты можешь "размножить" файл при помощи dup()/dup2().
Re[3]: стандартное поведение ОС при доступе к файлам?
От: MaximE Великобритания  
Дата: 20.10.06 13:35
Оценка: 1 (1)
Аноним wrote:

> ME>На Линукс с read/write() все просто.

>
> ME>В ядре файл представлен структурой inode.
> ME>http://www.linux-m32r.org/lxr/http/source/include/linux/fs.h#L539 В
> струтуре
> ME>есть mutex, который сериализует доступ к ней. Соответственно,
> процессы будут
> ME>выполнять read()/write() по очереди.
>
> Блин, не может всё быть так отстойно!

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

> Почему параллельные записи в начало и конец файла должны ждать друг друга?


Они не ждут.

write() в файл — всегда асинхронная операция (кроме случая, если файл открыт с
O_SYNC). write() лишь копирует данные из user space в ядерный буфер и обновляет
atime/mtime/etc. структуры inode. Данные из ядерного буфера вываливаются на диск
позже ядерным демоном pdflush. pdflush управляется политикой i/o scheduling.
http://www.redhat.com/magazine/008jun05/features/schedulers/

--
Maxim Yegorushkin

No Microsoft product was used in any way to write or send this text.
If you use a Microsoft product to read it, you're doing so at your own risk
Posted via RSDN NNTP Server 2.0
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.