Хорошо, ребята, есть миллиард демонстраций, относящихся к dup, dup2, fcntl, pipe и всевозможным вещам, которые прекрасны, когда существует несколько процессов. Однако мне еще предстоит увидеть одну очень простую вещь, которая, как я думаю, поможет объяснить поведение pipe и его отношение к стандарту снаружи и внутри.
Моя цель - просто (в том же процессе) перенаправить стандартный вывод через конвейер обратно на стандартный вывод напрямую. Я уже выполнил это с помощью промежуточных этапов, которые перенаправляют вывод канала в файл или записывают в буфер ... а затем возвращают стандартный вывод туда, где он начался. На этом этапе, конечно, я могу записать буфер обратно в стандартный вывод, но я не хочу этого делать.
Поскольку я переместил стандартный вывод в другое место в таблице файлов, я хотел бы направить вывод канала, чтобы он подавался непосредственно в новое стандартное положение вывода и печатал, как обычно.
Я чувствую, что есть какой-то слой вокруг таблицы файлов, который я не понимаю.
#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;
}
РЕДАКТИРОВАТЬ ********* Хорошо, я знаю, что std out каким-то образом берет информацию из таких команд, как 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
. - person Some programmer dude   schedule 16.09.2016stdout
концом канала для записи, и ваша программа сможет записывать данные в канал (думая, что он пишет вstdout
). Но другой конец трубы нельзя напрямую подключить к исходномуstdout
. Некоторый фрагмент кода должен читать из конвейера и записывать данные в исходныйstdout
. - person user3386109   schedule 16.09.2016read
, чтобы извлечь сообщение из канала и сохранить его в строке, а затем вы вызываетеwrite
, чтобы извлечь сообщение из строки и сохранить его в файле. Вот что я имею в виду под частью кода. Это код, который читает из канала и записывает данные в файл. Итак, если у вас где-то сохранен исходный дескриптор файлаstdout
, вы можете делать то же самое для чтения из канала и записи в исходный дескриптор файлаstdout
. - person user3386109   schedule 17.09.2016int fdin=open("tmp.in",O_RDONLY)
. А консоль - это файл только для записи, как если бы вы сделалиint fdout=open("tmp.out",O_WRONLY)
. Эти два файловых дескриптора не будут взаимодействовать друг с другом. Если вы хотите, чтобы они разговаривали, вам нужен код дляread
от одного иwrite
для другого. - person user3386109   schedule 17.09.2016