Передача стандартного вывода команды на стандартный ввод другого другого пользователя с использованием общего файла и dup2 () - PullRequest
2 голосов
/ 13 июля 2020

Я пишу программу с двумя аргументами - именем команд. Программа должна перенаправить вывод первой в файл 'tmp', чем выполнить его, затем перенаправить стандартный ввод второй команды в 'tmp' и выполнить вторую команду.


#include<unistd.h>
#include<fcntl.h>
#include<wait.h>
#include<stdio.h>

int main(int argc, char** argv){
    int fd = open("tmp", O_RDWR |O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
    int cpid = fork();
    
    if(cpid == 0){  
        dup2(fd, 1);
        execlp(argv[1], "", NULL);          
    }
    
    wait(NULL); 
    //If we uncoment this line the program gives correct output
    //fd = open("tmp", O_RDWR, S_IRUSR | S_IWUSR);
 
    dup2(fd, 0);
    
    execlp(argv[2], "", NULL);  
}

Однако, когда я запускаю программа типа ./main ls wc вместо 5 5 50 я получаю вывод 0 0 0, что означает, что команда wc считывает 0 байтов из stdin. Но если я вместо этого создаю дескриптор файла заново в том же файле tmp, программа выдаст правильный результат. Как можно объяснить такое поведение?

1 Ответ

2 голосов
/ 13 июля 2020

Этот вопрос в основном дублирует Может ли кто-нибудь объяснить простое описание, касающееся «дескриптора файла» после fork ()? , но, поскольку это немного тонко, я объясню этот конкретный случай c.

  1. Процесс открывает файл. Это создает описание файла . Описание файлов - это промежуточное понятие между файлами и дескрипторами файлов. Они не представлены напрямую в Unix API, но у них есть важное свойство в дополнение к файлу, на который они указывают, что мы увидим через минуту.
  2. Потомок записывает в это описание файла . Родитель ждет.
  3. Родитель читает из описания файла.

В конце шага 2 позиция файла в этом описании файла является концом файла. Итак, на шаге 3 родительский элемент начинает чтение в конце файла.

Если вы добавите вызов rewind(fd) после wait(NULL), дочерний элемент будет читать с начала файла.

Если вы откроете тот же файл с новым вызовом open, это создаст новое описание файла. open помещает позицию в новом описании файла в начало файла, если вы не установили режим добавления.

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

...