dup2, execv, каналы, разветвление и код, работающий в неправильном порядке

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

#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.

Такое ощущение, что некоторые из этих системных вызовов просто выполняются в том порядке, в каком они чувствуют, практически независимо от порядка, в котором я их написал, что делает практически невозможным что-либо делать с ними.

0

Решение

Используя входной файл с именем ‘colorfile.txt’, например:

color
color color
color color color
color color color color

Я обновил ваш код, чтобы сделать его dup2-ing и отладочные сообщения по-разному. Самое важное изменение (как я уже упоминал в своем комментарии к вашему вопросу) — это закрыть сторону записи канала в родительском процессе, чтобы избежать зависания этого процесса. Также важно (для целей отладки и для устранения путаницы относительно порядка событий) использование 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

Если вы понимаете, почему одно сообщение красочное, а другое красочное, вы начинаете понимать.

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]