Чтение онлайн

ЖАНРЫ

Основы программирования в Linux
Шрифт:

$ od -с /proc/9118/cmdline

0000000 f t p \0 1 9 2 . 1 6 8 . 0 . 1 2

0000020 \0

0000021

Из полученного вывода видно, что

ftp
была запущена из командной строки
ftp 192.163.0.12
.

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

ftp
есть открытые
дескрипторы 0, 1, 2 и 3. Они включают стандартные дескрипторы ввода, вывода и потока ошибок плюс подключение к удаленному серверу.

$ ls /proc/9118/fd

0 1 2 3

Более сложные приемы: fcntl и mmap

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

fcntl

Системный вызов

fcntl
предоставляет дополнительные методы обработки низкоуровневых дескрипторов файлов:

#include <fcntl.h>

int fcntl(int fildes, int cmd);

int fcntl(int fildes, int cmd, long arg);

С помощью системного вызова

fcntl
вы можете выполнить несколько разнородных операций над открытыми дескрипторами файлов, включая их дублирование, получение и установку флагов дескрипторов файлов, получение и установку флагов состояния файла и управление блокировкой файла (advisory file locking).

Различные операции выбираются разными значениями параметра команды

cmd
, как определено в файле fcntl.h. В зависимости от выбранной команды системному вызову может потребоваться третий параметр
arg
.

fcntl(fildes, F_DUPFD, newfd)
— этот вызов возвращает новый дескриптор файла с числовым значением, равным или большим целочисленного параметра
newfd
. Новый дескриптор — копия дескриптора
fildes
. В зависимости от числа открытых файлов и значения
newfd
этот вызов может быть практически таким же, как вызов
dup(fildes)
.

fcntl(fildes, F_GETFD)
— этот вызов возвращает флаги дескриптора файла, как определено в файле fcntl.h. К ним относится
FD_CLOEXEC
, определяющий, закрыт ли дескриптор файла после успешного вызова одного из системных вызовов семейства exec.

fcntl(fildes, F_SETFD, flags)
— этот вызов применяется для установки флагов дескриптора файла, как правило, только
FD_CLOEXEC
.

fcntl(fildes, F_GETFL)
и
fcntl(fildes, F_SETFL, flags)
— эти вызовы применяются, соответственно, для получения и установки флагов состояния файла и режимов доступа. Вы можете извлечь режимы доступа к файлу с помощью маски
O_ACCMODE
, определенной в файле fcntl.h. Остальные флаги включают передаваемые значения в третьем аргументе вызову open с использованием
O_CREAT
. Учтите, что вы не можете задать все флаги. В частности, нельзя задать права доступа к файлу с помощью вызова fcntl.

Вызов

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

mmap

Система UNIX

предоставляет полезное средство, позволяющее программам совместно использовать память, и, к счастью, оно включено в версию 2.0 и более поздние версии ядра Linux. Функция
mmap
(для отображения памяти) задает сегмент памяти, который может читаться двумя или несколькими программами и в который они могут записывать данные. Изменения, сделанные одной программой, видны всем остальным.

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

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

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

#include <sys/mman.h>

void *mmap(void *addr, size_t len, int prot, int flags, int fildes, off_t off);

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

off
. Открытый дескриптор файла задается в параметре
fildes
. Объем данных, к которым возможен доступ (т. е. размер сегмента памяти), указывается в параметре
len
.

Параметр

addr
можно использовать для запроса конкретного адреса памяти. Если он равен нулю, результирующий указатель формируется автоматически. Последний вариант рекомендуется, потому что в противном случае трудно добиться переносимости; диапазоны доступных адресов в разных системах отличаются.

Параметр

prot
используется для установки прав доступа к сегменту памяти. Он представляет собой результат поразрядной операции or, примененной к следующим константам:

PROT_READ
— сегмент может читаться;

PROT_WRITE
— в сегмент можно писать;

PROT_EXEC
— сегмент может выполняться;

PROT_NONE
— к сегменту нет доступа.

Параметр

flags
контролирует, как изменения, сделанные программой в сегменте, отражаются в других местах; его возможные значения приведены в табл. 3.7.

Таблица 3.7

Константа Описание
MAP_PRIVATE
Сегмент частный, изменения локальные
MAP_SHARED
Изменения сегмента переносятся в файл
MAP_FIXED
Сегмент должен располагаться по заданному адресу
addr

Функция

msync
вызывает запись изменений в части или во всем сегменте памяти обратно а отображенный файл (или считывание из файла).

#include <sys/mman.h>

int msync(void *addr, size_t len, int flags);

Корректируемая часть сегмента задается передачей начального адреса

addr
и размера
len
. Параметр
flags
управляет способом выполнения корректировки с помощью вариантов, приведенных в табл. 3.8.

Поделиться с друзьями: