Совместный доступ к файлам родительского и дочернего процессов

Каждый дочерний процесс наследует от своего родительского процесса все файлы, открытые родителем до вызова fork. Это означает, что любой дочерний процесс может использовать соответствующие дескрипторы файлов, значения которых были установлены родительским процессом во время операции открытия файлов. При выполнении fork значения этих дескрипторов копируются в область данных дочернего процесса, и после этого дочерний процесс может использовать эти дескрипторы для доступа к соответствующим файлам параллельно с родительским процессом. Дочерний процесс также наследует текущий каталог родительского процесса и его права доступа к файлам.

Если родитель и его дочерний процесс имеют одновременный доступ к одним и тем же файлам, то может возникать условие гонок, или состязаний.

Задание 6. В данной программе sharfile.c родительский и дочерний процессы параллельно копируют один и тот же входной файл в один и тот же выходной файл. Добавьте в программу контроль количества входных параметров, а также функцию perror для каждого системного вызова open, creat, read и write (за исключением write на терминал).

 

/* Program sharfile.c Usage: progname source_file destination_file

* for example: sharfile sharfile.c shar.bak

*/

#include <stdio.h>

#include <fcntl.h>

main (int argc,char *argv[])

{

int fdrd,fdwt;

char c;

char parent = 'P';

char child ='C';

int pid;

unsigned long i;

if (argc != 3) exit (1);

if ((fdrd = open(argv[1], O_RDONLY)) == -1) exit (1);

if ((fdwt = creat(argv[2], 0666)) == -1) exit (1);

printf("Parent: creating a child processn");

pid = fork ();

if (pid == 0)

{

printf("Child process starts, id = %dn",getpid());

for (;;)

{

if (read (fdrd, &c, 1) != 1) break;

for (i=0; i<50000;i++); /* Long cycle */

write(1,&child,1);

write (fdwt, &c, 1);

}

exit (0);

}

else

{

printf("Parent starts, id= %dn", getpid());

for (;;)

{

if (read (fdrd, &c, 1) != 1) break;

for (i=0;i<50000;i++); /* Long cycle */

write(1,&parent,1);

write (fdwt, &c, 1);

}

wait (0);

}

}

6.1. Подготовьте произвольный текстовый файл для копирования размером 500-1000 байтов. Можно взять исходный текст данной программы.

6.2. Запустите на выполнение созданный Вами исполнимый файл данной программы при помощи командной строки, содержащей два параметра: имя входного файла и имя выходного файла (имена должны быть разными).

6.3. Сравните результирующий файл с исходным файлом. Совпадают ли они?

6.4. Повторите пп. 6.2-6.3 несколько раз. Всегда ли результирующий файл один и тот же? Объясните причину несовпадения входного и выходного файлов. Примите во внимание, что процессы читают и записывают по одному байту каждой операцией read или write.

6.5. Добавьте в Вашу программу возможность измерять время (в микросекундах), необходимое для копирования файла. (Используйте функцию gettimeofday. Ее описание получите с помощью команды man.). Замерьте время копирования файла двумя процессами. Затем для сравнения исключите один процесс из операции копирования и замерьте время, необходимое для копирования файла одним процессом. Запишите в отчет Ваши результаты и выводы.