Реализация канала зависла в команде dup2
Я пытаюсь сделать простую оболочку, но я застрял в реализации труб. Вот часть моего кода, которая относится к трубе. Я могу добавить еще кое-что, если вы думаете, что это поможет, но остальное работает точно так, как ожидалось.
args[i] = NULL;
p_flag = 1;
int stop = i;
// we have to fork again so we can write to a buffer file.
// First we creat the pipe.
if (pipe(p_file) == -1) {
//check if the pipe failed
fprintf(stderr, "There was an error creating the pipe\n");
}
switch (pid = fork()) {
case 0:
//Open up the input end of the pipe for writing.
printf("test1\n");
close(p_file[0]);
printf("test2\n");
dup2(p_file[1], 1);
printf("test3\n");
execvp(args[0], args);
fprintf(stderr, "ERROR %s no such program.\n", line);
exit(1);
break;
case -1:
fprintf(stderr, "ERROR can't create child process!\n");
break;
default:
wait();
break;
}
/*
at this point only the first child should still be running
and since we waited we know that the buffer file has our input.
Now we have to redirect our input to read from the buffer and
run the rest of the commands normally. first the args array has
to be cleaned up we want the commands past the pipe symbol to be
in front.
*/
int j = 0;
stop++;
while (args[stop] != NULL) {
args[j] = args[stop];
j++;
stop++;
}
args[j] = NULL;
close(p_file[1]);
dup2(p_file[0], 0);
Как вы можете видеть, я вставил несколько операторов печати, чтобы попытаться выяснить, где именно он застрял, и я получаю test1
а также test2
вывод перед тем, как программа сядет, обрабатывая вечно крутящиеся колеса. Я должен Ctrl+ C, чтобы получить подсказку обратно. Я не знаю, почему он застрял, делая dup2
команда. Единственная важная вещь, оставленная в этом фрагменте кода, это инициализация p_file
и это массив размера два (т.е. int p_file[2];
).
1 ответ
У тебя серьезное заблуждение. Трубы являются механизмом межпроцессного взаимодействия. Процессы, связывающиеся через канал, обычно выполняются одновременно, а не последовательно. Они должны выполняться одновременно в реализации общего назначения, такой как предоставляемая оболочкой, потому что каждый канал имеет только конечный буфер, и запись в него будет блокироваться или завершаться сбоем при заполнении буфера. Если вы не можете быть уверены, что пишущий (ие) не заполнит буфер канала перед выходом, читатели должны быть готовы и ожидать получения данных из конца чтения канала, прежде чем вы сможете ожидать писателя (ей). заканчивать.
Поэтому неправильно wait()
для первого процесса перед запуском второго, и это может быть причиной того, что ваша программа зависает. Вместо этого оболочка должна запустить дочерний процесс для каждого конца канала, а затем ждать обоих.
Кроме того, как я написал в комментариях, вы звоните wait()
без правильных аргументов. Это приводит к неопределенному поведению, которое само по себе может быть неопределенным ожиданием, но также может быть почти любым другим.
Что касается ваших результатов отладки, @Ctx объяснил в своем комментарии, почему вы не видите всего, что ожидали. Однако я не вижу причин сомневаться в вашем утверждении о том, что программа зависает до тех пор, пока вы не прервете ее.