Я столкнулся с странной ошибкой при работе с Unix-каналами. Я написал короткую программу для демонстрации проблемы.C - труба Unix, close() влияет на выход?
Вот код:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char*args[]){
int fd[2];
pipe(fd);
int pid = fork();
if(pid<0){
perror("fork()");
exit(1);
}else if(pid == 0){
close(fd[0]);
const char* msg = "I'm here\n";
size_t len = strlen(msg) + 1; // +1 for null char
write(fd[1], msg, len);
while(1){/*does other work*/}
}else{
close(fd[1]);
}
pid = fork();
if(pid<0){
perror("fork()");
exit(1);
}else if(pid == 0){
close(fd[0]);
const char* msg = "I'm here\n";
size_t len = strlen(msg) + 1; // +1 for null char
write(fd[1], msg, len);
while(1){/*does other work*/}
}else{
close(fd[1]);
}
//close(fd[1]);
sleep(5);
const char* msg = "I'm here\n";
size_t len = strlen(msg) + 1; // +1 for null char
char str[len];
fcntl(fd[0],F_SETFL, O_NONBLOCK);
if(read(fd[0], str, len)<=0){
printf("Nothing from child\n");
}
/*does other work*/
fcntl(fd[0],F_SETFL, O_NONBLOCK);
if(read(fd[0], str, len)<=0){
printf("Nothing from child\n");
}
printf("finished read\n");
/*does other work*/
wait(NULL);
return 0;
}
родительского процесса вилы двух детей и создает канал. Два дочерних процесса записываются в канал, родительский считывает из канала.
Родительский процесс должен восстанавливать всю информацию, написанную ребенком.
Однако, когда я бегу выше программы, родительские распечатывает
Nothing from child
finished read
Почему?
Интересно, если я пишу один близко (FD [1]), как это:
#include <stdio.h>
#include <signal.h>
#include <sys/types.h>
#include <ctype.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#include <fcntl.h>
int main(int argc, char*args[]){
int fd[2];
pipe(fd);
int pid = fork();
if(pid<0){
perror("fork()");
exit(1);
}else if(pid == 0){
close(fd[0]);
const char* msg = "I'm here\n";
size_t len = strlen(msg) + 1; // +1 for null char
write(fd[1], msg, len);
while(1){/*does other work*/}
}else{
}
pid = fork();
if(pid<0){
perror("fork()");
exit(1);
}else if(pid == 0){
close(fd[0]);
const char* msg = "I'm here\n";
size_t len = strlen(msg) + 1; // +1 for null char
write(fd[1], msg, len);
while(1){/*does other work*/}
}else{
}
close(fd[1]);//HERE IS THE DIFFERENCE
sleep(5);
const char* msg = "I'm here\n";
size_t len = strlen(msg) + 1; // +1 for null char
char str[len];
fcntl(fd[0],F_SETFL, O_NONBLOCK);
if(read(fd[0], str, len)<=0){
printf("Nothing from child\n");
}
/*does other work*/
fcntl(fd[0],F_SETFL, O_NONBLOCK);
if(read(fd[0], str, len)<=0){
printf("Nothing from child\n");
}
printf("finished read\n");
/*does other work*/
wait(NULL);
return 0;
}
Он работает, он также работает, если я не близко (FD [1]) на всех. Я теряюсь, почему позиция close() влияет на чтение труб?
Почему, по вашему мнению, это нормально закрыть fd [1] дважды? –
В первом примере вы закрываете сторону записи трубы перед тем, как развить второй дочерний элемент, чтобы ребенок не мог записывать в трубку. Вы исправляете это, перемещая закрытие. Что за вопрос? –
А, я понимаю. Спасибо, я забыл, что у второго ребенка конец записи будет закрыт! – Noodles