Главная » 2017 » Ноябрь » 19 » man 2 kcmp
22:48
man 2 kcmp

SEO sprint - Всё для максимальной раскрутки!





ИМЯ


kcmp - сравнивает два процесса, определяя используют ли они общий ресурс ядра



ОБЗОР


#include <linux/kcmp.h>

int kcmp(pid_t pid1, pid_t pid2, int type,
unsigned long idx1, unsigned long idx2);

Замечание: В glibc нет обёрточной функции для данного системного вызова; смотрите
ЗАМЕЧАНИЯ.



ОПИСАНИЕ


Системный вызов kcmp() может использоваться для проверки, используют ли два
процесса pid1 и pid2 общий ресурс ядра, например виртуальную память, файловые
дескрипторы и т.д.

Право вызывать kcmp() определяется проверкой режима доступа ptrace
PTRACE_MODE_READ_REALCREDS вместе с pid1 и pid2; смотрите ptrace(2).

В аргументе type указывается какой ресурс двух процессов нужно сравнивать.
Допустимы следующие значения:

KCMP_FILE
Проверить, что файловый дескриптор idx1 в процессе pid1 указывает на то же
открытое файловое описание (смотрите open(2)) что и файловый дескриптор
idx2 в процессе pid2. Существование двух файловых дескрипторов, ссылающихся
на одно файловое описание, может возникнуть в результате вызова dup(2)
подобного) в fork(2), или передачи файловых дескрипторов через доменный
сокет (смотрите unix(7)).

KCMP_FILES
Проверить, используют ли процессы общий одинаковый набор открытых файловых
дескрипторов. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в
описании флага CLONE_FILES в clone(2).

KCMP_FS
Проверить, используют ли процессы общую одинаковую информацию о файловой
системе (т. е. маску прав создания, рабочий каталог и корень файловой
системы). Аргументы idx1 и idx2 игнорируются. Подробности смотрите в
описании флага CLONE_FS в clone(2).

KCMP_IO
Проверить, используют ли процессы общее контекст ввода-вывода. Аргументы
idx1 и idx2 игнорируются. Подробности смотрите в описании флага CLONE_IO в
clone(2).

KCMP_SIGHAND
Проверить, используют ли процессы общую одинаковую таблицу обработчиков
сигналов. Аргументы idx1 и idx2 игнорируются. Подробности смотрите в
описании флага CLONE_SIGHAND в clone(2).

KCMP_SYSVSEM
Проверить, используют ли процессы общий одинаковый список отмены операций
семафоров System V. Аргументы idx1 и idx2 игнорируются. Подробности
смотрите в описании флага CLONE_SYSVSEM в clone(2).

структуры:

struct kcmp_epoll_slot {
__u32 efd;
__u32 tfd;
__u64 toff;
};

В этой структуре поле efd содержит файловый дескриптор epoll, возвращаемый
epoll_create(2), tfd содержит номер файлового дескриптора, а toff содержит
смещение в файле назначения, начиная с нуля. Несколько разных назначений могут
быть зарегистрированы с одним номером файлового дескриптора, а установка
определённого смещения помогает выбрать нужный.

Заметим, что вызов kcmp() не защищён от ложных срабатываний (false positives),
которые могут случаться, если процессы в этот момент выполняются. То есть для
получения достоверных результатов перед выполнением данного системного вызова
нужно послать процессам сигнал SIGSTOP (смотрите signal(7)).



ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ


При успешном выполнении kcmp() возвращает результат арифметического сложения
указателей ядра (когда ядро сравнивает ресурсы, оно использует их адреса памяти).

Для простоты объяснения рассмотрим пример. Предположим, что v1 и v2 — адреса
соответствующих ресурсов и возвращается значение:

0 v1 равен v2; другими словами, два процесса используют ресурс совместно.

1 v1 меньше v2.

2 v1 больше v2.

3 v1 не равен v2, но нужная информация недоступна.

В случае ошибки возвращается -1 и значение errno устанавливается соответствующим
образом.

Значения вызова kcmp() специально выбраны так, чтобы их легко можно было
упорядочить. В частности, это удобно когда нужно сравнить большое количество
файловых дескрипторов.



ОШИБКИ


EBADF Значение type равно KCMP_FILE и fd1 или fd2 не являются открытыми файловыми
дескрипторами.

EINVAL Значение type неверно.

EPERM Недостаточно прав для просмотра ресурсов процесса. Для проверки процессов
требуется мандат CAP_SYS_PTRACE, которого у вас нет. Также могут
действовать другие ограничения ptrace, например CONFIG_SECURITY_YAMA,
которое при /proc/sys/kernel/yama/ptrace_scope равном 2, ограничивает
kcmp() дочерними процессами; смотрите ptrace(2).

ESRCH Процесс pid1 или pid2 не существует.

EFAULT Слот epoll, указанный в idx2, находится за пределами пользовательского
адресного пространства.



ЗАМЕЧАНИЯ


В glibc нет обёртки для данного системного вызова; запускайте его с помощью
syscall(2).

Данный системный вызов доступен только, если ядро собрано с параметром
CONFIG_CHECKPOINT_RESTORE. Основное предназначение вызова — возможность
засечки/восстановления в пользовательском пространстве (CRIU). Альтернативой этому
системному вызову было бы выставление соответствующей информации о процессе в
файловой системе proc(5); такой вариант не пригоден по причинам безопасности.

Дополнительную информацию об общих ресурсах смотрите в clone(2).



ПРИМЕР


Данная программа использует kcmp() про проверки того, что пара файловых
дескрипторов указывает на одно и тоже открытое файловое описание. Программа
тестирует различные случаи для пар файловых дескрипторов, описанных в выводе
программы. Пример работы программы:

$ ./a.out
PID родителя 1144
Открытый родителем файл на FD 3

PID потомка после fork() равен 1145
Сравнение дубликатов FD из других процессов:
kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> одинаков
Открытый потомком файл на FD 4
Сравнение FD из различных open() одного процесса:
kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> отличается
Дубликат FD 3 потомка для создания FD 5
Сравнение дубликатов FD одного процесса:
kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> одинаков

Исходный код программы

#define _GNU_SOURCE
#include <sys/syscall.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/kcmp.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)

static int
kcmp(pid_t pid1, pid_t pid2, int type,
unsigned long idx1, unsigned long idx2)
{
return syscall(SYS_kcmp, pid1, pid2, type, idx1, idx2);
}

static void
test_kcmp(char *msg, id_t pid1, pid_t pid2, int fd_a, int fd_b)
main(int argc, char *argv[])
{
int fd1, fd2, fd3;
char pathname[] = "/tmp/kcmp.test";

fd1 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd1 == -1)
errExit("open");

printf("PID родителя %ld\n", (long) getpid());
printf("Открытый родителем файл на FD %d\n\n", fd1);

switch (fork()) {
case -1:
errExit("fork");

case 0:
printf("PID потомка после fork() равен %ld\n", (long) getpid());

test_kcmp("Сравнение дубликатов FD из других процессов:",
getpid(), getppid(), fd1, fd1);

fd2 = open(pathname, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
if (fd2 == -1)
errExit("open");
printf("Открытый потомком файл на FD %d\n", fd2);

test_kcmp("Сравнение FD из различных open() одного процесса:",
getpid(), getpid(), fd1, fd2);

fd3 = dup(fd1);
if (fd3 == -1)
errExit("dup");
printf("Дубликат FD %d потомка для создания FD %d\n", fd1, fd3);

test_kcmp("Сравнение дубликатов FD одного процесса:",
getpid(), getpid(), fd1, fd3);
break;

default:
wait(NULL);
}

exit(EXIT_SUCCESS);
}



СМОТРИТЕ ТАКЖЕ


clone(2), unshare(2)



Категория: (2) Системные вызовы ядра (функции языка Си) | Просмотров: 368 | Добавил: Администратор | Рейтинг: 0.0/0
Всего комментариев: 0
avatar