Хорошо, ребята, есть миллиард демок, связанных с dup, dup2, fcntl, трубой и всеми видами вещей, которые замечательны, когда существует несколько процессов. Тем не менее, мне еще предстоит увидеть одну очень основную вещь, которая, я думаю, поможет объяснить поведение трубы и ее связь со стандартными и вне.Как использовать dup и dup2 для перенаправления стандартного вывода в трубу, а затем на antoher pipe, а затем обратно в стандартную версию?
Моя цель - просто (в том же процессе) перенаправить стандартный вывод через обратно обратно к стандартному выходу. Я уже выполнил это с промежуточными этапами, которые перенаправляют вывод трубы в файл или записывают в буфер ... и затем возвращают стандартный вывод туда, где он был запущен. В этот момент, конечно, я могу записать буфер обратно в stdout, но я не хочу этого делать.
Поскольку я переместил стандартный вывод в другое место в таблице файлов, я хотел бы направить вывод трубы на прямой канал в новую стандартную выходную позицию и напечатать его, как обычно.
Я чувствую, что вокруг таблицы файлов есть какой-то слой, который я не понимаю.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
int pipeEnds_arr1[2];
char str1[] = "STRING TO FEED INTO PIPE \n"; // make a string array
pipe(pipeEnds_arr1);
printf("File Descriptor for pipe ends from array\nPOSITION out 0 : %d\nPOSITION in 1 : %d\n", pipeEnds_arr1[0], pipeEnds_arr1[1]);
/* now my goal is to shift the input of the pipe into the position of
* standard output, so that the print command feeds the pipe, then I
* would like to redirect the other end of the pipe to standard out.
*/
int someInt = dup(1); // duplicates stdout to next available file table position
printf ("Some Int FD: %d\n", someInt); // print out the fd for someInt just for knowing where it is
/* This is the problem area. The out end of the pipe never
* makes it back to std out, and I see no way to do so.
* Stdout should be in the file table position 5, but when
* I dup2 the output end of the pipe into this position ,
* I believe I am actually overwriting std out completely.
* But I don't want to overwrite it, i want to feed the output
* of the pipe into std out. I think I am fundamentally
* misunderstanding this issue.
*/
dup2(pipeEnds_arr1[1], 1); //put input end of pipe into std out position
//dup2(pipeEnds_arr1[0], 5); // this will not work
//and other tests I have conducted do not work
printf("File Descriptor for pipe ends from array\nPOSITION out 0 : %d\nPOSITION in 1 : %d\n", pipeEnds_arr1[0], pipeEnds_arr1[1]);
fflush(stdout);
close(pipeEnds_arr1[0]);
close(pipeEnds_arr1[1]);
return 0;
}
EDIT ********* Хорошо, что я знаю, что-то из StD берет информацию из таких команд, как Printf, а затем раутов его в буфер, который затем продувают в оболочку.
Я считаю, что должен быть способ разбить «прочитанный» или выходной конец трубы на тот же самый буфер, который затем попадает в оболочку. Я выяснил, как разбить вывод трубы на строку, а затем я могу сделать, как мне заблагорассудится. В примере кода я пост ниже, я буду первым разгромить трубу к строке, а затем открыть файл и записать строку дескриптора файла этого файла ...
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
int main() {
/* Each pipe end array has to have 2 positions in it. The array
* position represents the two pipe ends with the 0 index
* position representing the output of the pipe (the place you want
* read your data from), and 1 index position representing the
* input file descriptor of the pipe (the place you want to write
* your data).
*/
int pipeEnds_arr1[2];
char str1[] = "Hello, we are feeding this into the pipe that we are through stdout into a pipe and then reading from the pipe and then feeding that output into a file \n"; // make a string array
/* Here we want to actually do the pipe command. We feed it the array
* with the 2 positions in it which will now hold file descriptors
* attached to the current process which allow for input and output
* through the new pipe. At this point, we don't know what the
* exact file decriptors are, but we can look at them by printing
*/
pipe(pipeEnds_arr1);
printf("File Descriptor for pipe ends from array\nPOSITION out 0 : %d\nPOSITION in 1 : %d\n", pipeEnds_arr1[0], pipeEnds_arr1[1]);
/* now my goal is to shift the input of the pipe into the position of
* standard output, so that the print command feeds the pipe, then we
* will try to read from the pipe and redirect the output to the std
* or in this test case out to a file.
*/
int someInt = dup(1); // we moved what was stdout into someInt;
/* put the write end of the pipe in the old stdout position by
* using dup2 so we will print directly into the pipe
*/
dup2(pipeEnds_arr1[1], 1);
/* this is where id like to re-rout the pipe back to stdout but
* im obviously not understanding this correctly
*/
//dup2(someInt, 3);
/* since std out has now been replaced by the pipe write end, this
* printf will print into the pipe
*/
printf("%s", str1);
/* now we read from the pipe into a new string we make */
int n;
char str2[strlen(str1)];
n = read(pipeEnds_arr1[0], str2, sizeof(str2)-1);
str2[n] = 0;
/* open a file and then write into it from the output of the pipe
* that we saved into the str2
*/
int fd = open("tmp.out", O_WRONLY | O_CREAT | O_TRUNC, 0644);
write(fd, str2, strlen(str2));
/* not sure about these last commands and their relevance */
fflush(stdout);
close(pipeEnds_arr1[0]);
close(pipeEnds_arr1[1]);
close(fd);
return 0;
}
Стандартный вывод - всегда * дескриптор файла '1'. То, что у вас есть в 'someInt', - это дескриптор, отличный от дескриптора' 1' после вашего вызова 'dup2'. Система 'dup' действительно вызывает * дубликаты * дескрипторов, не использует ссылки или ссылки или что-то в этом роде. Кроме того, вызовы 'dup' не изменяют номера дескрипторов, которые вы передаете. 'pipeEnds_arr1 [1]' не будет изменять значение (номер дескриптора) в любое время после вызова 'pipe'. –
Это не может работать в любом случае. Один конец трубы предназначен для записи, другой конец для чтения. Таким образом, вы можете заменить «stdout» на конец записи в трубе, и ваша программа может писать материал в трубу (думая, что она пишет «stdout»). Но другой конец трубы не может быть напрямую подключен к исходному «stdout». Некоторая часть кода должна читать из трубы и записывать данные в исходный 'stdout'. – user3386109
Это не может работать даже в теории, потому что это создаст бесконечный цикл. Подумайте об этом - вы в конечном итоге будете кормить выход из stdout обратно в себя. – kfx