| close_range(2) | System Calls Manual | close_range(2) |
close_range - закрыть все файловые дескрипторы в указанном диапазоне
Стандартная библиотека языка C (libc, -lc)
#define _GNU_SOURCE /* см. feature_test_macros(7) */ #include <unistd.h>
#include <linux/close_range.h> /* Definition of CLOSE_RANGE_*
constants */
int close_range(unsigned int first, unsigned int last, int flags);
Системный вызов close_range() закрывает все открытые файловые дескрипторы от first до last (включительно).
Ошибки закрытия указанного файлового дескриптора в настоящее время игнорируются.
flags - это битовая маска, содержащая 0 или более из следующих:
В случае успеха close_range() возвращает 0. В случае ошибки возвращается -1 и errno устанавливается для указания ошибки.
Следующее может произойти с CLOSE_RANGE_UNSHARE (при построении новой таблицы дескрипторов):
Отсутствуют.
FreeBSD. Linux 5.9, glibc 2.34.
To avoid blindly closing file descriptors in the range of possible file descriptors, this is sometimes implemented (on Linux) by listing open file descriptors in /proc/self/fd/ and calling close(2) on each one. close_range() can take care of this without requiring /proc and within a single system call, which provides significant performance benefits.
Дескрипторы файлов можно безопасно закрыть с помощью
/* нам не нужно ничего после stderr */ close_range(3, ~0U, CLOSE_RANGE_UNSHARE); execve(....);
CLOSE_RANGE_UNSHARE концептуально эквивалентен
unshare(CLONE_FILES); close_range(first, last, 0);
but can be more efficient: if the unshared range extends past the current maximum number of file descriptors allocated in the caller's file descriptor table (the common case when last is ~0U), the kernel will unshare a new file descriptor table for the caller up to first, copying as few file descriptors as possible. This avoids subsequent close(2) calls entirely; the whole operation is complete once the table is unshared.
This is particularly useful in cases where multiple pre-exec setup steps risk conflicting with each other. For example, setting up a seccomp(2) profile can conflict with a close_range() call: if the file descriptors are closed before the seccomp(2) profile is set up, the profile setup can't use them itself, or control their closure; if the file descriptors are closed afterwards, the seccomp profile can't block the close_range() call or any fallbacks. Using CLOSE_RANGE_CLOEXEC avoids this: the descriptors can be marked before the seccomp(2) profile is set up, and the profile can control access to close_range() without affecting the calling process.
The program shown below opens the files named in its command-line arguments, displays the list of files that it has opened (by iterating through the entries in /proc/PID/fd), uses close_range() to close all file descriptors greater than or equal to 3, and then once more displays the process's list of open files. The following example demonstrates the use of the program:
$ touch /tmp/a /tmp/b /tmp/c $ ./a.out /tmp/a /tmp/b /tmp/c /tmp/a opened as FD 3 /tmp/b opened as FD 4 /tmp/c opened as FD 5 /proc/self/fd/0 ==> /dev/pts/1 /proc/self/fd/1 ==> /dev/pts/1 /proc/self/fd/2 ==> /dev/pts/1 /proc/self/fd/3 ==> /tmp/a /proc/self/fd/4 ==> /tmp/b /proc/self/fd/5 ==> /tmp/b /proc/self/fd/6 ==> /proc/9005/fd ========= About to call close_range() ======= /proc/self/fd/0 ==> /dev/pts/1 /proc/self/fd/1 ==> /dev/pts/1 /proc/self/fd/2 ==> /dev/pts/1 /proc/self/fd/3 ==> /proc/9005/fd
Обратите внимание, что строки, показывающие имя пути /proc/9005/fd, являются результатом вызовов opendir(3).
#define _GNU_SOURCE
#include <dirent.h>
#include <fcntl.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <unistd.h>
/* Show the contents of the symbolic links in /proc/self/fd */
static void
show_fds(void)
{
DIR *dirp;
char path[PATH_MAX], target[PATH_MAX];
ssize_t len;
struct dirent *dp;
dirp = opendir("/proc/self/fd");
if (dirp == NULL) {
perror("opendir");
exit(EXIT_FAILURE);
}
for (;;) {
dp = readdir(dirp);
if (dp == NULL)
break;
if (dp->d_type == DT_LNK) {
snprintf(path, sizeof(path), "/proc/self/fd/%s",
dp->d_name);
len = readlink(path, target, sizeof(target));
printf("%s ==> %.*s\n", path, (int) len, target);
}
}
closedir(dirp);
}
int
main(int argc, char *argv[])
{
int fd;
for (size_t j = 1; j < argc; j++) {
fd = open(argv[j], O_RDONLY);
if (fd == -1) {
perror(argv[j]);
exit(EXIT_FAILURE);
}
printf("%s opened as FD %d\n", argv[j], fd);
}
show_fds();
printf("========= About to call close_range() =======\n");
if (close_range(3, ~0U, 0) == -1) {
perror("close_range");
exit(EXIT_FAILURE);
}
show_fds();
exit(EXIT_FAILURE);
}
Русский перевод этой страницы руководства разработал(и) Azamat Hackimov <azamat.hackimov@gmail.com>, Dmitriy S. Seregin <dseregin@59.ru>, Dmitry Bolkhovskikh <d20052005@yandex.ru>, Katrin Kutepova <blackkatelv@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 |