2013-03-31 2 views
1

Вот что я хотел бы сделать:двое дети чтение из трубы

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

я получаю что-то вроде этого в один терминальном окне: Nejke аа , а во втором: ADT Я хочу: данные Nejake

Я пытался искать в Интернете, но я прошу так или иначе. Любая помощь очень ценится.

#include <stdlib.h> 
#include <stdio.h> 
#include <string.h> 
#include <fcntl.h> 
#include <sys/stat.h> 

/* declare our procedures */ 
void runchild1(int pfd[]); 
void runchild2(int pfd[]); 

/* some data to write and read from pipe */ 
const char some_data[] = "Nejake data" ; 




int main(int argc, char **argv) 
{ 
int pid, status;    //PID for debugging 
int fd[2];      //file descriptors for the   pipe 

/* let create some pipe */ 
pipe(fd); 

/* supposed to run two children of the process */ 
runchild1(fd); 
runchild2(fd); 

/* this is important! close both file descriptors on the pipe */ 
close(fd[0]); close(fd[1]);  

/* pick up all the dead children */ 
while ((pid = wait(&status)) != -1) 
    fprintf(stderr, "process %d exits with %d\n", pid, WEXITSTATUS(status)); 
exit(0); 
} 



void runchild1(int pfd[]) /* run the first child */ 
{ 
int pid;    /* you may want to print it for debugging */ 
int data_processed;  /* store data */ 
int des;    /* descriptor for open files */ 
char buffer;   /* buffer for reading byte of data */ 

switch (pid = fork()) { 

case 0:     /* child reads from the pipe */ 

    close(pfd[1]);  /* this process don't need the other end */ 
    while ((data_processed = read(pfd[0],&buffer,1)) > 0) { 

     printf("Proces %d, data citane po bajte: %c\n",getpid(),buffer); 
     des = open("/dev/ttys001",O_RDWR); 
     write(des, &buffer,1);   
    }    
    exit(0); 

default: /* parent writes to the pipe */  

    /* write some data for children to read */ 
    data_processed = write(pfd[1], some_data, strlen(some_data)); 
    printf("Zapis %d bytov cez nepomenovanu ruru:\n", data_processed); 
    printf("Zapisane: %s\n",some_data); 
    printf("Som rodic dvoch deti: %d\n",getpid()); 

    break; 

case -1: 
    perror("fork"); 
    exit(1); 
} 
} 


void runchild2(int pfd[]) /* run the second child */ 
{ 
int pid; 
int data_processed; 
int des; 
char buffer; 

switch (pid = fork()) { 

case 0:     /* child */ 

    close(pfd[1]);  /* this process doesn't need the other end */ 
    while ((data_processed = read(pfd[0],&buffer,1)) > 0) { 

     printf("Proces %d, data citane po bajte: %c\n",getpid(),buffer); 
     des = open("/dev/ttys002",O_RDWR); 
     write(des, &buffer,1);   
    } 
    exit(0);   


default: /* parent does nothing */ 
    break; 

case -1: 
    perror("fork"); 
    exit(1); 
} 
} 
+2

Я не совсем уверен, что я понимаю проблему. Вы хотите, чтобы оба ребенка увидели «данные Неяке»? Каждый байт, который вы пишете, будет читаться одним и только одним ребенком; так работают трубы. Когда один ребенок читает его, он недоступен для другого ребенка. Таким образом, один ребенок получает некоторые данные, а другой ребенок получает остальную часть данных. Если вы хотите, чтобы оба ребенка получили все данные, вам придется записать их дважды и использовать что-то вроде файла внешней блокировки с fcntl, чтобы дети рассказывали друг другу, когда они будут сделаны. – rra

+0

точно, я хочу, чтобы оба ребенка прочитали все данные, потому что мне нужно, чтобы они выводили его в отдельное окно терминала, поэтому я должен посмотреть на fcntl ... – user2229608

+0

посмотреть исходный код утилиты 'tee'? Удачи. – shellter

ответ

0

Unix труба - FIFO. Один вход, один выход. Ничего похожего на два выхода из одной трубы. Ваши читы: System V IPC ключевое слово и ipcs команда.

+0

Хорошо, спасибо всем за ваши комментарии и ответы, я сейчас это понимаю. – user2229608

2

Если двум детям необходимо отобразить одни и те же данные, вам понадобятся две трубы, по одному на каждого ребенка, а родительский должен записывать каждое сообщение дважды, один раз на каждом канале.

В качестве альтернативы, вы можете запустить команду tee с process substitution, или вы можете посмотреть вверх (поищите вверх) программа pee (процесс/труба вариант tee) - или вы можете по ссылкам из этого Stack Overflow answer. У вашей программы будет одна труба, но у каждого будет своя труба.