Архитектура Аудит Военная наука Иностранные языки Медицина Металлургия Метрология Образование Политология Производство Психология Стандартизация Технологии |
Переход от общего к частному
Это наша первая встреча со множеством абстракций, в которые мы погрузились во время движения от слоя обобщенной файловой системы к слою специальной файловой системы. Рис. 6.17 иллюстрирует то, как структура файла указывает на таблицу операций специфической файловой системы. Вспомните, что при вызове read_inode (), inode заполняется информацией, включающей поле fop, указывающее на соответствующую таблицу операций, определенную в реализации специфической файловой системы (например, ext2). При создании файла или монтировании слой специфической файловой системы инициализирует свою структуру файловых операций. Так как теперь мы работаем с файловой системой ext2, структура файловых операций будет следующей: Глава 6* Файловые системы
Рис. 6.17. Файловые операции fs/ext2/file.c 42 struct file__operations ext2_file_operations 43.llseek = generic_f ile_llseek, 44.read = generic_file_read, 45.write = generic__file_write, 46.aio_read = generic_file_aio_read, 47.aio_write = generic_file_aio_write, 48.ioctl = ext2_ioctl, 49.ramap = generic__f ile_mmap/ 50.open = generic_file_open/ 51.release *= ext2L_release_f ile, 52.fsync = ext2_sync—file, 53.readv = generic_file_readv, 54.writev = generic_file_writev/ 55.sendfile = generic_file_sendfile/ 56 }; Вы можете заметить, что практически в каждой файловой операции файловая система ext2 решает, использовать ли решения Linux по умолчанию. Отсюда возникает вопрос: когда файловая система может захотеть использовать собственную реализацию файловых операций? Когда файловая система существенно отличается от используемых в UNIX, могут потребоваться дополнительные шаги для того, чтобы Linux смогла с ней Системные вызовы VFS и слой файловой системы работать. Например, для DOS- или FAT-файловых систем необходимо реализовать собственную операцию записи, но тем не менее использовать стандартную функцию чтения1. Рассмотрим, как слой специфической файловой системы ext2 передает управление слою обобщенной файловой системы, и начнем с рассмотрения generic_f ile_read(). Mm/filemap.c 924 ssize_t 925 generic_file_read(struct file *filp, char _ user *buf, size^t count, loff_t *ppos) 926 { 927 struct iovec Iocal_iov = {. iov_base = buf, .iov_len = count }; 928 struct kiocb kiocb; 929 ssize__t ret; 930
931 init_sync_Jciocb(& kiocb, filp); 932 ret = ____ generic_r_file_aio_read(& kiocb, & Iocal_iov, 1, ppos); 933 if (-EIOCBQUEUED =- ret) 934 ret = wait_on_sync_Jciocb(& kiocb); 935 return ret; 936 } 938 EXPORTjSYMB0L(generic_file_read); Строки 924-925 Обратите внимание, что параметры просто передаются из функции чтения более высокого уровня. У нас есть filp, файловый указатель; buf, указатель на буфер в памяти, куда читается файл; count, количество символов для чтения, и ppos, позиция в файле, откуда начинается чтение. Строка 927 Создается структура iovec, содержащая адреса и длину буфера пользовательского пространства, в который будут сохранены результаты чтения. Строки 928 и 931 Инициализируется структура kiocb с помощью файлового указателя. [Kiokcb расшифровывается как kernel I/O control block (блок ядра управления вводом-выводом).] Строка 932 Основная работа выполняется обобщенной функцией асинхронного чтения. 1 Более подробную информацию см. в файле fs/fat/f ile.c. Глава 6 • Файловые системы Асинхронные операции ввода-вывода Типы данных kiocb и iovec отвечают за операции асинхронного ввода-вывода в ядре Linux. Асинхронный ввод-вывод полезен, когда процесс желает выполнить операцию ввода или вывода без ожидания поступления результата операции. Он особенно полезен для высокоскоростного ввода-вывода, так как предоставляет устройству возможность сортировать и планировать запросы ввода-вывода вместо самого процесса. В Linux вектор ввода-вывода (iovec) предоставляет диапазон адресов памяти и определен как include/linux/uio.h 20 struct iovec 21 { 22 void _ user *iov_base; /* BSD использует caddr_t (1003.1g требует void *) */ 23 __ kernel_size_t iov_len; /* Должна быть size_t (1003.lg) */ 24 }; Это простой указатель на раздел памяти и длину памяти. Блок ядра управления вводом-выводом (kiocb) - это структура, необходимая для определения того, когда и как обрабатывать вектор асинхронного ввода-вывода. Функция__ generic_f ile_aio_read () использует структуры kiocb и iovec для прямого чтения page_cache. Строки 933-935 После того как мы запустили чтение, мы ожидаем, пока чтение закончится, и затем возвращаем результат в операцию чтения. Вспомните путь do_sync_read () в vf s_read (); здесь эта функция будет запус mm/filemap.c 835 ssize_t 83 6 _ generic_file_aio_read(struct kiocb *iocb/ const struct iovec *iov, 837 unsigned long nr_segs, loff_t *ppos) 838 { 83 9 struct file *filp = iocb-> ki_filp; 840 ssize_t retval; 841 unsigned long seg; 842 size_t count; 843 Системные вызовы VFS и слой файловой системы 844 count = 0; 845 for (seg = 0; seg < nr_segs; seg++) { 846 const struct iovec *iv = & iov[seg]; 852 count += iv-> iov_len; 853 if (unlikely((ssize_t)(count|iv-> iov_len) < 0)) 854 return -EINVAL; 855 if (access_ok(VERIFY_WRITE, iv-> iov_base, iv-> iov_len) ) 856 continue; 857 if (seg == 0) 858 return -EFAULT; 859 nr_segs = seg; 860 count -= iv-> iov_len 861 break; 862 } Строки 835-842 Вспомните, что nr_segs устанавливается в 1 в нашем вызове и что iocb и iov хранят файловый указатель и информацию о буфере. Сразу после этого мы извлекаем файловый указатель из iocb. Строки 845-862 Этот цикл for проверяет передаваемую структуру iovec, состоящую их корректных сегментов. Вспомните, что она содержит информацию о буфере пользовательского пространства. mm/filemap.с 864 /* объединение iovecs и пересылка direct-to-BIO для 0_DIRECT */ 865 if (filp-> f_flags & 0_DIRECT) {
866 loff_t pos = *ppos, size; 867 struct address_space *mapping; 868 struct inode *inode; 869
870 mapping = filp-> f_mapping; 871 inode = mapping-> host; 872 retval = 0; 873 if (! count) 874 goto out; /* skip atime */ 875 size = i_size_read(inode); 876 if (pos < size) { 877 retval = generic_file_direct_IO(READ, iocb, 878 iov, pos, nr_segs); Глава 6 • Файловые системы 879 if (retval > = 0 & & ! is_jsync_kiocb(iocb)) 880 retval = -EIOCBQUEUED; 881 if (retval > 0) 882 *ppos = pos + retval; 883 } 884 f ile__accessed(filp); 885 goto out; 886 } Строки 863-886 Этот фрагмент кода просто входит в чтение из прямого ввода-вывода. Прямой ввод-вывод передает кеш страниц и используется при работе с блочными устройствами. Для наших целей нам тем не менее вообще не нужно заходить в этот фрагмент кода. Основная масса файлового ввода-вывода происходит в файловом кеше, который мы вскоре опишем, что значительно быстрее, чем непосредственная работа с блочным устройством. mm/filemap.c 888 retval = 0; 889 if (count) {
890 for (seg = 0; seg < nr_segs; seg++) { 891 read_descriptor_t desc; 892
893 desc.written = 0; 894 desc.buf = iov[seg].iov_base; 895 desc.count = iov[seg].iov_len; 896 if (desc.count == 0) 897 continue; 898 desc.error = 0; 899 do_generic_f ile_read(filp, ppos, & desc, f ile_read_actor); 900 retval += desc.written; 901 if (! retval) {
902 retval = desc.error; 903 break; 904 } 905 } 906 } 907 out: 908 return retval; 909 } Популярное:
|
Последнее изменение этой страницы: 2016-03-25; Просмотров: 824; Нарушение авторского права страницы