| kcmp(2) | System Calls Manual | kcmp(2) |
kcmp - сравнивает два процесса, определяя используют ли они общий ресурс ядра
Стандартная библиотека языка C (libc, -lc)
#include <linux/kcmp.h> /* определения констант KCMP_* */ #include <sys/syscall.h> /* определения констант SYS_* */ #include <unistd.h>
int syscall(SYS_kcmp, pid_t pid1, pid_t pid2, int type,
unsigned long idx1, unsigned long idx2);
Note: glibc provides no wrapper for kcmp(), necessitating the use of syscall(2).
Системный вызов kcmp() может использоваться для проверки, используют ли два процесса pid1 и pid2 общий ресурс ядра, например виртуальную память, файловые дескрипторы и т.д.
Право вызывать kcmp() определяется проверкой режима доступа ptrace PTRACE_MODE_READ_REALCREDS вместе с pid1 и pid2; смотрите ptrace(2).
В аргументе type указывается какой ресурс двух процессов нужно сравнивать. Допустимы следующие значения:
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 — адреса соответствующих ресурсов и возвращается значение:
В случае ошибки возвращается -1, а errno устанавливается в значение ошибки.
Значения вызова kcmp() специально выбраны так, чтобы их легко можно было упорядочить. В частности, это удобно когда нужно сравнить большое количество файловых дескрипторов.
Linux.
Linux 3.5.
Before Linux 5.12, this system call is available only if the kernel is configured with CONFIG_CHECKPOINT_RESTORE, since the original purpose of the system call was for the checkpoint/restore in user space (CRIU) feature. (The alternative to this system call would have been to expose suitable process information via the proc(5) filesystem; this was deemed to be unsuitable for security reasons.) Since Linux 5.12, this system call is also available if the kernel is configured with CONFIG_KCMP.
Дополнительную информацию об общих ресурсах смотрите в clone(2).
Данная программа использует kcmp() про проверки того, что пара файловых дескрипторов указывает на одно и тоже открытое файловое описание. Программа тестирует различные случаи для пар файловых дескрипторов, описанных в выводе программы. Пример работы программы:
$ ./a.out Parent PID is 1144 Parent opened file on FD 3 PID of child of fork() is 1145 Compare duplicate FDs from different processes: kcmp(1145, 1144, KCMP_FILE, 3, 3) ==> same Child opened file on FD 4 Compare FDs from distinct open()s in same process: kcmp(1145, 1145, KCMP_FILE, 3, 4) ==> different Child duplicated FD 3 to create FD 5 Compare duplicated FDs in same process: kcmp(1145, 1145, KCMP_FILE, 3, 5) ==> same
#define _GNU_SOURCE #include <err.h> #include <fcntl.h> #include <linux/kcmp.h> #include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <sys/syscall.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> 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, pid_t pid1, pid_t pid2, int fd_a, int fd_b) {
printf("\t%s\n", msg);
printf("\t\tkcmp(%jd, %jd, KCMP_FILE, %d, %d) ==> %s\n",
(intmax_t) pid1, (intmax_t) pid2, fd_a, fd_b,
(kcmp(pid1, pid2, KCMP_FILE, fd_a, fd_b) == 0) ?
"same" : "different"); } int main(void) {
int fd1, fd2, fd3;
static const char pathname[] = "/tmp/kcmp.test";
fd1 = open(pathname, O_CREAT | O_RDWR, 0600);
if (fd1 == -1)
err(EXIT_FAILURE, "open");
printf("Parent PID is %jd\n", (intmax_t) getpid());
printf("Parent opened file on FD %d\n\n", fd1);
switch (fork()) {
case -1:
err(EXIT_FAILURE, "fork");
case 0:
printf("PID of child of fork() is %jd\n", (intmax_t) getpid());
test_kcmp("Compare duplicate FDs from different processes:",
getpid(), getppid(), fd1, fd1);
fd2 = open(pathname, O_CREAT | O_RDWR, 0600);
if (fd2 == -1)
err(EXIT_FAILURE, "open");
printf("Child opened file on FD %d\n", fd2);
test_kcmp("Compare FDs from distinct open()s in same process:",
getpid(), getpid(), fd1, fd2);
fd3 = dup(fd1);
if (fd3 == -1)
err(EXIT_FAILURE, "dup");
printf("Child duplicated FD %d to create FD %d\n", fd1, fd3);
test_kcmp("Compare duplicated FDs in same process:",
getpid(), getpid(), fd1, fd3);
break;
default:
wait(NULL);
}
exit(EXIT_SUCCESS); }
Русский перевод этой страницы руководства разработал(и) Alex Nik <rage.iz.me@gmail.com>, Azamat Hackimov <azamat.hackimov@gmail.com>, Yuri Kozlov <yuray@komyakino.ru>, Иван Павлов <pavia00@gmail.com> и Kirill Rekhov <krekhov.dev@gmail.com>
Этот перевод является свободной программной документацией; он распространяется на условиях общедоступной лицензии GNU (GNU General Public License - GPL, https://www.gnu.org/licenses/gpl-3.0.html версии 3 или более поздней) в отношении авторского права, но БЕЗ КАКИХ-ЛИБО ГАРАНТИЙ.
Если вы обнаружите какие-либо ошибки в переводе этой страницы руководства, пожалуйста, сообщите об этом разработчику(ам) по его(их) адресу(ам) электронной почты или по адресу списка рассылки русских переводчиков.
| 15 июня 2024 г. | Справочные страницы Linux 6.9.1 |