Я изо всех сил пытаюсь правильно понять fork()
, pipe()
и execvp()
и хотел бы получить руководство о том, где я ошибаюсь с этим кодом, и куда мне следует идти отсюда.Насколько я понимаю, если вы хотите запустить несколько процессов, вы fork()
n раз используете оператор for
, как показано ниже.Чтобы сохранить ссылку на каждый коммуникационный «канал» между родителем и многочисленными дочерними элементами, вы используете дескриптор файла 2D (например, fd[n][2]
).Кроме того, чтобы разрешить связь двумя способами, вы используете 2 FD.При вызове exevp()
он заменяет вызванный процесс на процесс, созданный execvp()
.
Итак, я создал простую программу, которая разветвляет 2 копии процесса, единственной целью которого является немедленное возвращение строки, отправленной родительским процессом.С этого момента он должен отправить сообщение дочернему процессу 0, затем дочернему процессу 1. Затем вечно ждет, пока что-то не будет сделано, чтобы завершить дочерний процесс или родительский процесс.Тем не менее, я сталкиваюсь с 2 проблемами.Во-первых, эта текущая программа останавливается на первом операторе read
/ printf
в родительском процессе, и я получаю следующий результат, предлагающий мне ввести значения, которые ничего не делают, когда я нажимаю клавишу ввода.Я знаю, что эта ошибка возникает из-за моей программы execvp
, поскольку удаление fgets
и просто printf
, ввод значения и выход работают, как и ожидалось.Однако мне нужно fgets
, потому что я хочу иметь возможность вернуться к этому процессу и позже отправить ему больше сообщений.
Child 0
| <--- Prompts me to enter value
Ожидается:
Child 0
Process 0 received: test message
Child 1
Process 1 received: test message
Вот моя основная программа:
int main () {
char buff[50];
int pipe_parent[2][2];
int pipe_child[2][2];
int pids[2];
for (int i = 0; i < 2; i++) {
char id[snprintf(NULL, 0, "%d", i) + 1];
sprintf(id, "%d", i);
char* prog[] = {"./test", id, NULL};
if (pipe(pipe_parent[i]) == -1 || pipe(pipe_child[i]) == -1) {
exit(1);
}
int pid = fork();
if (pid > 0) {
pids[i] = pid;
close(pipe_child[i][0]);
close(pipe_parent[i][1]);
int in = pipe_child[i][1];
int out = pipe_parent[i][0];
write(out, "test message\n", 13); //hard coded but should use strlen + 1
read(in, buff, 50);
//The code below does not work and so probably the read above too
printf("Child: %s", buff); //Does not print anything and starts waiting for use input here.
//Inputting anything here does nothing
} else if (pid == 0) {
print("Child %d", i);
close(pipe_child[i][1]);
close(pipe_parent[i][0]);
dup2(pipe_child[i][0], STDIN_FILENO);
dup2(pipe_parent[i][1], STDOUT_FILENO);
close(pipe_child[i][0]);
close(pipe_child[i][1]);
execvp(prog[0], prog);
exit(1); //Should not reach here unless error
} //Should add error check here with else
for (int i = 0; i < 2; i++) {
int status;
waitpid(pids[i], &status, 0);
}
return 0;
}
и моя другая программа, которая получает execvp
'd:
int main(int argc, char** argv) {
char buff[50];
while(fgets(buff, sizeof(buff), stdin) != NULL) {
printf("Process &d received: %s", atoi(argv[1]), buff);
}
printf("Process %d closed", atoi(argv[1]));
return 0;
}
Моя вторая проблема заключается в том, что, предполагая, что вышеуказанные программы работают, я не знаю, как работает связь с определенным процессом.Я хочу, чтобы программа работала так, чтобы она отправляла сообщение для обработки 0, затем 1, затем 0, .... и т. Д. (Или в любом другом порядке, указанном мной), пока что-то не будет сделано, чтобы остановить его.Я думаю, что код будет выглядеть примерно так для простого 0,1,0,1 ... code:
int counter = 0;
while(counter < 5) {
for (int i = 0; i < 2; i++) {
//setup out and in to be pipe_child/parent[i][0/1]
write(out, "message", len);
//read();
//printf();
}
counter++;
}
Если бы я мог получить подсказку о том, как это работает, тобудет с благодарностью.
Редактировать: execl()
до execvp()