• Некоторые /proc-файлы могут быть прочитаны только их владельцем (или привилегированным процессом). Например, все файлы, находящиеся в каталоге /proc/PID, являются собственностью пользователя, владеющего соответствующим процессом, и в отношении некоторых из них (например, /proc/PID/environ) права на чтение даются только владельцу файла.
• Кроме файлов в подкаталогах /proc/PID, большинство файлов в каталоге /proc являются собственностью суперпользователя (root), и те файлы, в которые разрешено вносить изменения, могут быть изменены только этим пользователем.
Обращение к файлам, находящимся в /proc/PID
Каталоги /proc/PID не существуют постоянно. Каждый из них появляется с созданием процесса с соответствующим идентификатором и исчезает, как только процесс завершится. То есть, определив факт существования конкретного каталога /proc/PID, нужно быть готовым обработать возможность того, что к моменту попытки открытия файла процесс уже мог завершиться и соответствующий каталог /proc/PID мог быть удален.
Пример программы
В листинге 12.1 показан способ чтения и изменения /proc-файла. Приведенная в нем программа считывает и отображает содержимое файла /proc/sys/kernel/pid_max. Если указан аргумент командной строки, программа обновляет файл, используя его значение. Этот файл (впервые появившийся в версии 2.6) указывает верхний предел для идентификаторов процесса (см. раздел 6.2). Пример работы программы выглядит следующим образом:
$ su
Password:
# ./procfs_pidmax 10000
Old value: 32768
/proc/sys/kernel/pid_max теперь содержит 10000
Листинг 12.1. Обращение к файлу /proc/sys/kernel/pid_max
sysinfo/procfs_pidmax.c
#include
#include "tlpi_hdr.h"
#define MAX_LINE 100
int
main(int argc, char *argv[])
{
int fd;
char line[MAX_LINE];
ssize_t n;
fd = open("/proc/sys/kernel/pid_max", (argc > 1)? O_RDWR: O_RDONLY);
if (fd == -1)
errExit("open");
n = read(fd, line, MAX_LINE);
if (n == -1)
errExit("read");
if (argc > 1)
printf("Old value: ");
printf("%.*s", (int) n, line);
if (argc > 1) {
if (write(fd, argv[1], strlen(argv[1]))!= strlen(argv[1]))
fatal("write() failed");
system("echo /proc/sys/kernel/pid_max now contains "
"'cat /proc/sys/kernel/pid_max'");
}
exit(EXIT_SUCCESS);
}
sysinfo/procfs_pidmax.c
Системный вызов uname() возвращает идентифицирующую информацию о базовой системе, в которой выполняется приложение в структуре, указанной аргументом utsbuf.
#include
int uname(struct utsname *
Возвращает 0 при успешном завершении или –1 при ошибке
Аргумент utsbuf является указателем на utsname-структуру, имеющую следующее определение:
#define _UTSNAME_LENGTH 65
struct utsname {
char sysname[_UTSNAME_LENGTH]; /* Название реализации */
char nodename[_UTSNAME_LENGTH]; /* Имя узла в сети */
char release[_UTSNAME_LENGTH]; /* Идентификатор выпуска ОС */
char version[_UTSNAME_LENGTH]; /* Версия ОС */
char machine[_UTSNAME_LENGTH]; /* Оборудование, на котором
запущена система */
#ifdef _GNU_SOURCE /* Далее следуют данные,
характерные для Linux */
char domainname[_UTSNAME_LENGTH]; /* Доменное имя хоста NIS */
#endif
};
В SUSv3 системный вызов uname() указан, но длина различных полей в структуре utsname не определена. Требуется только, чтобы строки завершались нулевым байтом. В Linux длина каждого из этих полей определена равна 65 байт, включая место для завершающего нулевого байта. В одних реализациях UNIX эти поля бывают короче, а в других (например, в Solaris) их длина доходит до 257 байт.
Поля sysname, release, version и machine структуры utsname автоматически заполняются ядром.
В Linux доступ к такой же информации, которая возвращается в полях sysname, release и version структуры utsname, дается в трех файлах каталога /proc/sys/kernel. Это файлы, предназначенные только для чтения, которые называются соответственно ostype, osrelease и version. Еще один файл, /proc/version, включает ту же информацию, что и эти три файла, а также сведения о компиляции ядра (то есть имя пользователя, выполнившего компиляцию, имя хоста, на котором она была выполнена, и версию gcc).
В поле nodename возвращается значение, установленное с использованием системного вызова sethostname() (подробности можно найти на странице руководства, посвященной этому системному вызову). Зачастую это имя похоже на префикс имени хоста из доменного имени системы в DNS.
В поле domainname возвращается значение, установленное с помощью системного вызова setdomainname() (подробности можно найти на соответствующей странице руководства). Это доменное имя хоста в сетевой информационной службе — Network Information Services (NIS) (не следует путать с доменным именем хоста в DNS).