read back something -> print what received. Бала ретінде пайдаланылатын бағдарлама кез келген кіріс жолын күтеді және stdout-ге бір"> read back something -> print what received. Бала ретінде пайдаланылатын бағдарлама кез келген кіріс жолын күтеді және stdout-ге бір"> read back something -> print what received. Бала ретінде пайдаланылатын бағдарлама кез келген кіріс жолын күтеді және stdout-ге бір" />

C: dup2, құбыр және шанышқы күткендей жұмыс істемейді

I'm trying to do a simple fork -> execute another program -> say "hello" to that child process -> read back something -> print what received.

Бала ретінде пайдаланылатын бағдарлама кез келген кіріс жолын күтеді және stdout-ге бір нәрсені басып шығарады «Сәлем».

Бұл менің «хост» бағдарламасы (ол жұмыс істемейді):

#include 
#include 
#include 

#define IN 0
#define OUT 1
#define CHILD 0

main ()
{
  pid_t pid;
  int pipefd[2];
  FILE* output;
  char buf[256];

  pipe(pipefd);

  pid = fork();    
  if (pid == CHILD)
  {
    printf("child\n");
    dup2(pipefd[IN], IN);
    dup2(pipefd[OUT], OUT);
    execl("./test", "test", (char*) NULL);
  }
  else
  {
    sleep(1);
    printf("parent\n");
    write(pipefd[IN], "hello!", 10);//write message to the process    
    read(pipefd[OUT], buf, sizeof(buf));
    printf("received: %s\n", buf);
  }
}

Мынаны аламын:

child
[.. waits 1 second ..]
parent
received: 

Мен не жоғалтып жатырмын? Рахмет!

EDIT (test.c):

Сұрау бойынша, бұл балалар бағдарламасы:

#include 
#include 
#include 

int getln(char line[])
{
  int nch = 0;
  int c;

  while((c = getchar()) != EOF)
    {
      if(c == '\n') break;
    line[nch] = c;
    nch++;
    }

 if(c == EOF && nch == 0) return EOF;
 return nch;
}

main()
{
  char line[20];

  getln(line);
  printf("hello there!", line);
  fflush(stdout);  
  return 0;
}
6

6 жауаптар

Сіз әрдайым файл-дескриптордан 0 файлынан оқып шығыңыз және құбырлармен бірге 1 файлдық-дескрипторына жазыңыз ... ата-аналармен қарым-қатынасыңызда осы қарым-қатынас қалпына келтірілді. Сіз не істеуді қаласаңыз, ата-ана мен бала арасындағы екі жақты қарым-қатынас жасау үшін екі құбырды қажет етуіңіз мүмкін, себебі ата-ана құбырға жазған мазмұнын оқып шыққан жағдайларды болдырмайды, себебі процесті жоспарлау шешілмейтін болып табылады (яғни, ата-ана баланың ата-анасының оқып-үйренуін оқығаннан кейін, ата-ана жазбаның аяқталуымен аяқтағаннан кейін оқитын болса, онда ата-ананың құбырға жазғаны туралы оқуға кепілдік берілмейді жазды).

Кодты төмендегіге өзгертіңіз:

main ()
{
  pid_t pid;
  int pipe_to_child[2];
  int pipe_from_child[2];
  FILE* output;
  char buf[256];

  pipe(pipe_to_child);
  pipe(pipe_from_child);

  pid = fork();    
  if (pid == CHILD)
  {
    printf("child\n");

    //child process not using these ends of the pipe, so close them
    close(pipe_to_child[1]);
    close(pipe_from_child[0]);

    dup2(pipe_to_child[0], fileno(stdin));
    dup2(pipe_from_child[1], fileno(stdout));

    execl("./test", "test", (char*) NULL);
  }
  else
  {
    sleep(1);
    printf("parent\n");
    write(pipe_to_child[1], "hello!\n", 10);//write message to the process    
    read(pipe_from_child[0], buf, sizeof(buf));
    printf("received: %s\n", buf);
  }
}
3
қосылды

Бұл үшін сізге екі құбыр қажет: біреуі бала үдерісінің stdin және біреуі үшін оның stdout. Сіз құбырдың екі ұштарын екі құбыр ретінде қайта пайдалана алмайсыз.

Сондай-ақ, ата-аналық бағдарламаның бұл жолы

write(pipefd[IN], "hello!", 10);//write message to the process    

жаңа жолды жазмайды, сондықтан getln ешқашан балаға қайтарылмайды. (Бұдан басқа, «сәлем!» Тек алты таңбадан тұрса да, онын жазасыз.)

2
қосылды

Сіздің құбырларыңыздың дескрипторлары араласқан сияқты. pipe() деп аталатыннан кейін pipefd [0] - құбырдың оқылған соңында және pipefd [1] - құбырдың жазу соңы. Сіз оқу соңына жазасыз және жазу соңынан оқи аласыз.

Сондай-ақ, сіз баланың үдерісінің both stdin және stdout бір құбырын пайдалануға тырысып жатырсыз. Менің ойымша, бұл шынымен сіз жасағыңыз келетін нәрсе (сізге екі құбыр қажет).

1
қосылды

pipefd [0] - бұл трубаның оқу соңы болып табылады, себебі оған жазу (ата-аналар сияқты) естімесіз болып табылады және сәтсіздікке ұшырайды. Сол сияқты pipefd [1] - жазба аяқталуы, одан оқып шығу (ата-ана сияқты) да сәтсіздікке ұшырайды. Оқу және жазу қоңырауларының қайтарылған мәндерін үнемі тексеріп, кез келген қателіктер жібергеніңізді білуіңіз керек

1
қосылды

wait немесе waitpid қолданыңыз керек.

1
қосылды

Басқалары құбырдың бір-біріне жақындағанын айтады, бұл менің алдымен ойладым. Бірақ шын мәнінде бұл менің адам бетінде айтқан сөздер емес:

 A read from fildes[0] accesses the data written to fildes[1]
 on  a  first-in-first-out  (FIFO)  basis  and  a  read  from
 fildes[1] accesses the data written to fildes[0] also  on  a
 FIFO basis.

Алайда, бұл ата-ана pipefd [0] -ге жазса, онда бала pipefd [1] -дан оқу керек дегенді білдіреді, сондықтан сіз баланың stdin және stdout құбыры бар.

Адам бетінде бір құбырмен жасай алатын сияқты көрінеді. Бірақ екеуін пайдаланудың айқын коды болуы мүмкін.

pipefd әр элементін жеке құбыр деп ойлайсың, бірақ бұлай емес.

1
қосылды
Ия, кепілдік берілген қос бағытты арна қажет болса socketpair немесе псевдотермин қажет.
қосылды автор zwol, көзі
POSIX спецификациясына сәйкес pipe , «Фильдтер [0] жазу үшін ашық және фильдтер [1] оқу үшін де ашықсыз ба, жоқ па?»
қосылды автор Jason, көзі