Марк Митчелл - Программирование для Linux. Профессиональный подход
if (readlink("/proc/self/exe", buffer, len) <= 0)
return -1;
/* Нахождение последней косой черты, отделяющей путевое имя. */
path_end = strrchr(buffer, '/');
if (path_end == NULL)
return -1;
/* Переход к символу, стоящему за последней косой чертой. */
++path_end;
/* Усечение полной строки до путевого имени. */
*path_end = ' ';
/* Длина путевого имени — это число символов до последней
косой черты. */
return (size_t)(path_end - buffer);
}
int main() {
char path[PATH_MAX];
get_executable_path(path, sizeof (path));
printf("this program is in the directory %en", path);
return 0;
}
7.2.5. Дескрипторы файлов процесса
Элемент fd файловой системы /proc — это подкаталог, в котором содержатся записи обо всех файлах, открытых процессом. Каждая запись представляет собой символическую ссылку на файл или устройство. Через эти ссылки можно осуществлять чтение и запись данных. Имена ссылок соответствуют номерам дескрипторов.
Рассмотрим небольшой трюк. Откройте новое терминальное окно и найдите с помощью команды ps идентификатор процесса, соответствующий интерпретатору команд:
% ps
PID TTY TIME CMD
1261 pts/4 00:00:00 bash
2455 pts/4 00:00:00 ps
В данном случае процесс идентификатора команд (bash) имеет идентификатор 1261. Теперь откройте второе окно и просмотрите содержимое подкаталога fd этого процесса:
% ls -l /proc/1261/fd total 0
lrwx------ 1 samuel samuel 64 Jan 30 01:02 0 -> /dev/pts/4
lrwx------ 1 samuel samuel 64 Jan 30 01:02 1 -> /dev/pts/4
lrwx------ 1 samuel samuel 64 Jan 30 01:02 2 -> /dev/pts/4
(В выводе могут присутствовать дополнительные строки, соответствующие другим открытым файлам.) Вспомните в разделе 2.1.4, "Стандартный ввод-вывод", рассказывалось о том. что дескрипторы 0, 1 и 2 закрепляются за стандартными потоками ввода, вывода и ошибок соответственно. Таким образом, при записи в файл /proc/1261/fd/1 данные будут направляться в устройство, связанное с потоком stdout интерпретатора команд, т.е. на псевдотерминал первого окна. Попробуйте ввести следующую команду
% echo "Hello, world." >> /proc/1261/fd/1
Сообщение "Hello, world." появится в первом окне.
В подкаталоге fd могут присутствовать ссылки и на другие файлы. В листинге 7.6 показана программа, которая открывает файл, указанный в командной строке, и переходит в бесконечный цикл.
Листинг 7.6. (open-and-spin.c) Открытие файла для чтения#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
const char* const filename = argv[1];
int fd = open(filename, O_RDONLY);
printf("in process %d, file descriptor %d is open to %sn",
(int)getpid(), (int)fd, filename);
while (1);
return 0;
}
Запустите программу в терминальном окне:
% ./open-and-spin /etc/fstab
in process 2570, file descriptor 3 is open to /etc/fstab
Теперь откройте другое окно и проверьте подкаталог fd процесса с указанным номером:
% ls -l /proc/2570/fd
total 0
lrwx------ 1 samuel samuel 64 Jan 30 01:30 0 -> /dev/pts/2
lrwx------ 1 samuel samuel 64 Jan 30 01:30 1 -> /dev/pts/2
lrwx------ 1 samuel samuel 64 Jan 30 01:30 2 -> /dev/pts/2
lr-x------ 1 samuel samuel 64 Jan 30 01:30 3 -> /etc/fstab
Как видите, появилась, ссылка 3, которая соответствует дескриптору файла /etc/fstab, открытого программой.
Программа может открывать дескрипторы не только файлов, но также сокетов и каналов. В таких случаях адресатом символической ссылки будет строка "socket" или "pipe", а не имя файла либо устройства.
7.2.6. Статистика использования процессом памяти
Файл statm содержит список из семи чисел, разделенных пробелами. Каждое число — это счетчик числа страниц памяти, используемых процессом и попадающих в определенную категорию. Соответствующие категории перечислены ниже (в порядке следования счетчиков):
■ общий размер процесса;
■ размер резидентной части процесса;
■ память, совместно используемая с другими процессами (например, загруженные библиотеки или нетронутые страницы, созданные в режиме "копирование при записи");
■ текстовый размер процесса, т.е. размер сегмента кода исполняемого файла;
■ размер совместно используемых библиотек, загруженных процессом;
■ память, выделенная под стек процесса;
■ число недействительных страниц, т.е. страниц памяти, которые были модифицированы программой.
7.2.7. Статистика процесса
Файл status содержит всевозможную информацию о процессе, отформатированную в понятном для пользователя виде. Сюда входит идентификатор процесса, идентификатор родительского процесса, реальный и эффективный идентификаторы пользователя и группы, статистика использования памяти, а также битовые маски, определяющие, какие сигналы перехватываются, игнорируются или блокируются.
7.3. Аппаратная информация
В файловой системе /proc есть ряд других элементов, позволяющих получить доступ к информации о системных аппаратных средствах. Обычно это интересно лишь системным администраторам, но иногда такая информация используется и в приложениях. Ниже описано несколько наиболее полезных файлов.
7.3.1. Центральный процессор
Как уже говорилось, файл /proc/cpuinfo содержит информацию о центральном процессоре (или процессорах, если их больше одного). В поле "processor" перечислены номера процессоров. В случае однопроцессорной системы там будет стоять 0. Благодаря полям "vendor_id", "cpu family", "model" и "stepping" можно точно узнать модель и модификацию процессора. В поле "flags" показано, какие флат процессора установлены. Это самая важная информация. Она определяет, какие функции процессора доступны. Например, флаг "mmx" говорит о том, что поддерживаются расширенные инструкции MMX.[23]
Большая часть информации, содержащейся в файле /proc/cpuinfo, извлекается с помощью ассемблерной инструкции cpuid процессоров семейства x86. С помощью этой низкоуровневой инструкции программы могут получать сведения о центральном процессоре. Подробнее узнать об этой инструкции можно в руководстве IA-32 Intel Architecture Software Developer's Manual, Volume 2: Instruction Set Reference, доступном по адресу http://developer.intel.com/design.
Последний элемент файла, bogomips, характерен для Linux. Это показатель скорости работы процессора в поглощающем цикле (когда программы обращаются к процессору, но не выполняют вычислений). Он не отражает общую производительность процессора.
7.3.2. Аппаратные устройства
В файле /proc/devices содержится список старших номеров символьных и блочных устройств, имеющихся в системе. Подробнее об этом рассказывалось в главе 6. "Устройства".
7.3.3. Шина PCI
В файле /proc/pci перечислены устройства, подключенные к шине (или шинам) PCI. Сюда входят реальные PCI-платы, а также устройства, встроенные в материнскую плату, плюс графические платы AGP. В каждой строке указан тип устройства, идентификатор устройства и его поставщика, имя устройства (если есть), информация о функциональных возможностях устройства и сведения о ресурсах PCI-шины, используемых устройством
7.3.4. Последовательные порты
Файл /proc/tty/driver/serial содержит конфигурационную и статистическую информацию о последовательных портах. Эти порты нумеруются начиная с нуля.[24] Работать с настройками порта позволяет также команда setserial, но файл /proc/tty/driver/serial, помимо всего прочего, включает дополнительные статистические данные о счетчиках прерываний каждого порта.
Например, следующая строка описывает последовательный порт 1 (COM2 в Windows):
1: uart:16550А port:2F8 irq:3 baud:9600 tx:11 rx:0
Здесь говорится о том, что последовательный порт оснащен микросхемой UART 16550А, использует порт ввода-вывода 0x218 и прерывание 3 и работает со скоростью 9600 бод. Через этот порт было передано 11 запросов на прерывание и получено 0 таких запросов.
7.4. Информация о ядре
В файловой системе /proc есть много элементов, содержащих информацию о настройках и состоянии ядра. Некоторые из них находятся на верхнем уровне файловой системы, а некоторые скрыты в каталоге /proс/sys/kernel.
7.4.1. Версия ядра
В файле /proc/version находится строка, описывающая номер версии и модификации ядра. В нее также включены сведения о создании ядра: имя пользователя, скомпилировавшего ядро, адрес компьютера, на котором это было сделано, дата компиляции и версия компилятора. Например: