1

Я изучаю операционные системы самостоятельно из лекций MOOC, доступных онлайн, и хотел работать на xv6. Я читал документацию по xv6 и в главе 0, когда речь идет о каналах (стр. 13) сомневаюсь.

int p[2];
char *argv[2];
argv[0] = "wc";
argv[1] = 0;

pipe(p);
if(fork()==0){
close(0);
dup(p[0]);
close(p[0]);
close(p[1]);
exec("/bin/wc", argv);
}
else{
write(p[1], "hello world\n", 12);
close(p[0]);
close(p[1]);}

Написано что:
Теперь дочерний элемент возвращает конец чтения в файловый дескриптор 0, закрывает fds в p и исполняет wc. Когда wc читает из стандартного ввода, он читает из канала. Родитель пишет в конец записи канала, а затем закрывает оба своих файловых дескриптора.

Также упоминается, что процессы не имеют общих переменных, т. Е. Изменения, внесенные в одном процессе, не отражаются в изменениях другого.

Теперь, здесь, я пишу в родительском процессе, и если child достигает exec до того, как parent заканчивает писать в p [1], child будет ждать, а после того, как он закончит запись, child будет читать из p [0] и будет выполнять exec. Итак, правильно ли говорить, что существуют специальные привилегии для каналов, которые заставляют их поддерживать межпроцессное взаимодействие посредством совместного использования каналов? Таким образом, в отличие от переменных, чьи изменения не будут отражаться в другом процессе, каналы являются общими, и, следовательно, их изменения отражаются друг в друге?
Правильно ли приведенные выше рассуждения?

1 ответ1

1

Ваши рассуждения в основном правильные. Не то чтобы трубы имели особые привилегии; ты просто думаешь о них как о неправильном. Канал не является переменной, это объект ОС, созданный в ядре с помощью системного вызова pipe , и может быть открыт в одном или нескольких процессах одновременно. Данные, записанные в доступный для записи конец канала (то есть второй из двух файловых дескрипторов, созданных в вызове pipe(p) и сохраненных в массиве p), доступны для чтения в другом файловом дескрипторе (p[0] здесь, который затем дублируется в дескриптор файла 0, который является дескриптором файла, используемым для стандартного stdin). Это чтение и запись в канал возможны независимо от того, в каких процессах открыты эти файловые дескрипторы.

Вы можете заметить, что вы не просто присваиваете значения каналам; вы write в них как файлы (а write - это системный вызов; программа говорит ядру сделать что-то, а не просто изменить значение в своей локальной памяти). На самом деле, если вы думаете о каналах как о файлах, за исключением того, что они могут быть анонимными (безымянными), не могут иметь файловые дескрипторы, способные как читать, так и записывать (то есть они являются однонаправленными), и хранить данные только между записью и чтение, а не после того, как данные прочитаны или все файловые дескрипторы в канал закрыты, вы не ошибетесь. Точно так же, как два процесса могут совместно использовать доступ к одному и тому же файлу, так и два процесса могут совместно использовать доступ к каналу (способ, показанный здесь, является распространенным способом создания канала для совместного использования двумя процессами, но вы можете также открыть два совершенно не связанных процесса "именованный канал", который является той же идеей, за исключением того, что вы даете ему имя, подобное файлу, и каждый процесс открывает один конец за раз и указывает, хочет ли он конец чтения или записи).

Создание каналов вручную обычно выполняется для межпроцессного взаимодействия, но не обязательно в исходном коде. Кроме того, обе программы не должны быть запущены одновременно. Если вы пишете строку в оболочке, используя | ("символ канала"), вы указываете оболочке создать канал из стандартного stdout первой команды в стандартный stdin второй команды (как и в примере выше, создается канал в стандартный stdin /bin/wc). То есть команда оболочки, такая как ls | wc) создает канал с доступным для записи концом, заданным в качестве файлового дескриптора 1 (stdout), выполняет ls и, таким образом, записывает свой вывод в этот канал, затем устанавливает читаемый конец в качестве файлового дескриптора 0 (stdin) и выполняет wc , который должным образом считывает выходные данные из готового ls и выводит результат на свой стандартный stdout , который попадает на ваш терминал.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .