Итак, что это должно делать, это fork, чтобы дочерний процесс получил текст файла, а затем родительский процесс изменил этот текст и записал его в новый файл. Из-за этого у меня есть странная странность. Весь код примерно такой.
#include <iostream>
#include <termios.h>
#include <cstdio>
#include <cstdlib>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <sys/wait.h>
using namespace std;
int parentPID;
int main(int argc, char* argv[]){
parentPID = getpid();
int pipey[2];
int worked = pipe(pipey);
if( worked == - 1){
cout << "Oops. Didn't make a pipe.";
}
//cout << "About to fork!!!";
fork();
if(getpid() != parentPID){//Only run in the child process
char* argvec1[3] = {"cat", "colorfile.txt", (char*)0};
dup2(pipey[1], 1);
execv("/bin/cat", argvec1);
}
else{//Only run in the parent process.
int someInt;
cout << "In the parent process";
pid_t status = wait(&someInt);
dup2(pipey[0], 0);
creat("newfile.txt", 0777);
chmod("newfile.txt", 0777);
int targetFile = open("newfile.txt", O_WRONLY);
if(targetFile == -1){
cout << "\nOops, couldn't open targetFile, ";
perror("because ");
}
else{
cout << "\nOpened target file.";
}
dup2(targetFile, 1);
//char* argvec2[] = {"sed", "-e", "s/color/colour/g", (char*)0};
//execv("/bin/sed", argvec2);
cout << "something went terribly wrong";
}
}
Особой проблемой являются три вещи: первый, этот фрагмент кода...
creat("newfile.txt", 0777);
chmod("newfile.txt", 0777);
int targetFile = open("newfile.txt", O_WRONLY);
if(targetFile == -1){
cout << "\nOops, couldn't open targetFile, ";
perror("because ");
}
else{
cout << "\nOpened target file.";
}
dup2(targetFile, 1);
... не записывает "Открытый целевой файл" в стандартный вывод. Вместо этого он помещает его в файл newfile.txt, так что dup2 меняет вывод на выходные команды, которые появляются перед ним?... если я прокомментирую dup2, в конце концов, этого не произойдет, это определенно то, что конкретный dup2 вызвав это.
во-вторых, этот фрагмент кода...
creat("newfile.txt", 0777);
chmod("newfile.txt", 0777);
int targetFile = open("newfile.txt", O_WRONLY);
if(targetFile == -1){
cout << "\nOops, couldn't open targetFile, ";
perror("because ");
}
else{
cout << "\nOpened target file.";
}
//dup2(targetFile, 1);
char* argvec2[] = {"sed", "-e", "s/color/colour/g", (char*)0};
execv("/bin/sed", argvec2);
cout << "something went terribly wrong";
... не выводит каких-либо успехов/сбоев в отношении открытия файла вообще. Он распечатывает содержимое исходного файла, соответствующим образом изменен, но не прекращается. Это просто вроде сидит навсегда, пока я не использую ctrl-C, чтобы убить текущий процесс. Окончательный cout не отображается.
Наконец, это...
creat("newfile.txt", 0777);
chmod("newfile.txt", 0777);
int targetFile = open("newfile.txt", O_WRONLY);
if(targetFile == -1){
cout << "\nOops, couldn't open targetFile, ";
perror("because ");
}
else{
cout << "\nOpened target file.";
}
dup2(targetFile, 1);
char* argvec2[] = {"sed", "-e", "s/color/colour/g", (char*)0};
execv("/bin/sed", argvec2);
cout << "something went terribly wrong";
... не получает никакого вывода ни на стандартный вывод, ни на файл newfile.txt.
Похоже, что некоторые из этих системных вызовов выполняются только в том порядке, в котором они себя чувствуют, независимо от порядка, который я им написал, что делает невозможным что-либо с ними делать.
Используя входной файл с именем "colorfile.txt", например:
color
color color
color color color
color color color color
Я обновил ваш код, чтобы сделать его dup2-ing и debug-сообщения по-разному. Самое важное изменение (как я упоминал в своем комментарии к вашему вопросу), заключается в том, чтобы закрыть сторону записи в канале в родительском процессе, чтобы избежать зависания этого процесса. Также важно (для целей отладки и борьбы с путаницей о порядке событий) является использование "endl" для сброса вывода. В противном случае ваши вызовы dup2 возникают, когда буферизованные данные все еще сохраняются и могут изменить назначение этих данных, по-видимому, после его написания, поскольку записи происходят, когда базовые библиотеки выгружаются, например, при выходе процесса.
Обратите внимание, что для труб я использую термины "сторона записи" и "сторона чтения", чтобы соответственно ссылаться на индексы 1 и 0 этого небольшого массива файловых дескрипторов, созданных каналом (2): стороны, которые пользователь канала пишет и читает.
Эти обновления нацелены на g++ (GCC) 4.8.2 на ядро Linux 3.10.17. Предположительно другие включают и т.д., Будут меняться.
#include <iostream>
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
using namespace std;
int main() {
int pipey[2];
if (pipe(pipey) == -1) {
perror("pipe failed");
return 1;
}
cout << "About to fork!!!" << endl;
pid_t pid = fork();
if (pid == -1) {
perror("fork failed");
return 1;
}
if (pid == 0) { // child process
const char *av[] = { "cat", "colorfile.txt", 0 };
cout << "In the child process" << endl;
cout << "colorful child message before dup2" << endl;
dup2(pipey[1], 1);
close(pipey[1]);
cout << "colorful child message after dup2" << endl;
close(pipey[0]);
execvp(av[0], (char * const *) av);
perror("failed to exec cat");
return 1;
} else { // parent process.
const char *av[] = { "sed", "-e", "s/color/colour/g", 0 };
cout << "In the parent process" << endl;
int targetFd = open("newfile.txt", O_CREAT|O_TRUNC|O_WRONLY, 0644);
if (targetFd == -1){
perror("failed to open newfile.txt");
return 1;
} else {
cout << "Opened target file." << endl;
}
cout << "colorful parent message before dup2s" << endl;
dup2(pipey[0], 0);
close(pipey[0]);
dup2(targetFd, 1);
close(targetFd);
cout << "colorful parent message after dup2s" << endl;
// The soon-to-be exec'd cat process will have the read side of
// the pipe duped to its stdin, and the child process created
// above *will* write data that cat will see, but unless the
// write side is closed by *all* its writers prior to exec (and
// this parent process is one of the writers), cat will see no
// end-of-file on its stdin.
//
// Note how easily this deadlock can be created, within a single
// process.
close(pipey[1]);
execvp(av[0], (char * const *) av);
perror("failed to exec sed");
return 1;
}
}
Когда я запускаю это, я вижу:
About to fork!!!
In the parent process
In the child process
colorful child message before dup2
Opened target file.
colorful parent message before dup2s
И содержимое выходного файла newfile.txt:
colorful parent message after dup2s
colourful child message after dup2
colour
colour colour
colour colour colour
colour colour colour colour
Если вы понимаете, почему одно сообщение красочное, а другое - красочное, вы ловите его.
<< endl
для принудительного вывода, но в большинстве случаев достаточно простого"\n"
в конце. Кроме того, поскольку вы не создаете исполняемые программы, x-биты в разрешении 0777 неуместны - 0666 или даже 0644 были бы более разумными.