Для начала немного переписал ваш код. В частности, обратите внимание, что дочерняя ветвь (PID == 0) завершается после завершения. Родитель закрывает переданные дескрипторы файлов после разветвления и в случае ошибки.
if (this->num_args == 2) {
int fd1 = open(args[1], O_RDONLY);
if (fd1 == -1) {
perror("open failed");
return;
}
int fd2 = open(args[2], O_TRUNC);
if (fd2 == -1) {
fd2 = open(args[2], O_CREAT, 0666);
if (fd2 == -1) {
perror("open failed");
close(fd1);
return;
}
}
pid_t PID = fork();
if (PID == -1) {
perror("fork failed");
} else if (PID == 0) {
char buff[1024];
int read_res = read(fd1, &buff, 1024); /// read from the file fd1 into fd2
while (read_res != -1) {
if (!read_res) {
break;
}
if (write(fd2, buff, read_res) == -1) {
perror("write failed");
}
read_res = read(fd1, buff, 1024);
}
if (read_res == -1) {
perror("read failed");
}
exit(0);
} else {
printf("Copy running in background (pid: %d)\n", PID);
}
close(fd1);
close(fd2);
return
}
Когда дочерний процесс вызывает exit
, процесс остается в состоянии «Zomb ie». Это состояние позволяет родительскому процессу (вам) вызывать wait
или waitpid
для получения кода выхода.
В качестве вторичного эффекта завершения процесса ядро отправит SIGCHLD
вашему процессу , чтобы вы знали, что вы действительно можете позвонить по номеру wait
без блокировки. В вашей ситуации вам не важен код выхода, поэтому вы можете настроить обработчик сигнала «безразлично» в начале своей программы и позволить ядру очистить процесс:
signal(SIGCHLD, SIG_IGN);
Это задокументировано в signal (2):
Если процесс явно указывает SIG_IGN как действие для сигнала SIGCHLD, система не будет создавать процессы-зомбы ie при выходе дочерних процессов вызывающего процесса . Как следствие, система отбросит статус выхода из дочерних процессов.