Как мой Linux C процесс узнает, сколько файлов было открыто в командной строке? - PullRequest
3 голосов
/ 18 января 2020

Когда я запускаю процесс в Linux, я могу передать несколько перенаправлений ввода и вывода. Например, если я хотел бы иметь 14 выходных файлов, я сделаю это:

command >f1 3>f2 4>f3 5>f4 6>f5 7>f6 8>f7 9>f8 10>f9 11>f10 12>f11 13>f12 14>f13 15>f14

Может ли моя команда точно знать, сколько таких файлов было передано в командной строке?

Я знаю, что всегда могу добавить параметр командной строки, например --count 14. Я надеюсь, что мы не должны.

Ответы [ 4 ]

3 голосов
/ 18 января 2020

Нет способа различить guish между перенаправлениями, установленными в командной строке, и перенаправлениями, которые уже присутствовали в среде выполнения.

Например, когда утилита util запускается в скрипте

exec 4<file4
# ...
util 3<file3

, она увидит как fd 3, так и fd 4 открыты для чтения; он не может сказать, что только один был открыт в командной строке. Если вы заботитесь об этом, что вы, вероятно, должны, потому что может быть несколько из них.

Помимо этого, вы, безусловно, можете выяснить, какие fds в данный момент открыты, например, просматривая все из них или просматривая псевдо-каталог /proc/self/fd. См. этот вопрос для некоторых примеров решений по поиску всех дескрипторов открытого файла в Linux.

2 голосов
/ 18 января 2020

Может ли моя команда точно знать, сколько таких файлов было передано в командной строке?

Да, если вы заказываете их последовательно. Вы можете open() фиктивный файл (например, /dev/null) и затем вычесть 3 из fd, возвращаемого open, чтобы получить количество дополнительных открытых файлов (кроме stdin, stdout и stderr) в процессе. Вы можете пройти через них oop, начав с 3 и повторяя циклы, пока не дойдете до манекена fd.

Пример:

int dummy_fd = open("/dev/null", O_RDONLY);
printf("number of files open: %d\n", dummy_fd - 3);
for(int fd_ctr = 3; fd_ctr < fd; fd_ctr++)
    /* ... */;
close(dummy_fd);

Я знаю, что всегда могу добавить параметр командной строки, например --count 14.

Хорошая идея. Пока вы занимаетесь этим, как насчет того, чтобы просто передавать имена файлов в качестве аргументов командной строки?

1 голос
/ 18 января 2020

На linux вы можете просто проверить файлы в /proc/self/fd/. Каждое имя файла будет соответствовать открытому файлу.

Пример программы:

#include <dirent.h>
#include <assert.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>

int main() {
        printf("Open fds:");
        DIR *dir = opendir("/proc/self/fd/");
        assert(dir != NULL);
        struct dirent *d;
        while (d = readdir(dir), d != NULL) {
                if (d->d_type != DT_LNK) continue;
                errno = 0;
                const int i = atoi(d->d_name);
                assert(errno == 0);
                printf(" %d", i);
        }
        printf("\n");
}

Когда выполняется это:

$ ./a.out 5>a 6>b 100>c
Open fds: 0 1 2 3 5 6 100
1 голос
/ 18 января 2020

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

Все, что может сделать ваш код, - это использовать файл ручки, которые были открыты для вас. Любые трюки, которые вы используете, чтобы найти максимально открытый дескриптор в вашем коде, не будут работать, если у вас есть пробелы, такие как:

command >f1 5>f5

Я подозреваю, что вам было бы лучше просто использовать параметры командной строки, чтобы сделать это, что-то например:

command --output=file1 --output=file2 --output==file3

Тогда у вас есть полный контроль над тем, как вы обрабатываете эти аргументы в своем коде. Например, вы можете создавать карту файлов при открытии каждого из них.

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

...