Я пытался написать код на C, используя вилки и каналы, где программа создает четыре процесса, которые взаимодействуют друг с другом через каналы. Связь основана на следующем дереве связи:
1
/ \
2 3
\ /
|
4
Первый процесс считывает n слов из файла с именем input.dat , где n дается как аргумент. Первый процесс отправляет слова второму и третьему процессу, используя разные каналы.
Второй процесс читает слова из конвейера и считает все гласные слово за словом. Если количество гласных четное, процесс заменяет каждую гласную на пару из двух (никаких изменений не требуется в случае нечетного числа), а затем присоединяет количество гласных к каждому слову.
Я уже задавал вопрос по этому поводу, вот ссылка с примерами: Как посчитать количество гласных в файле пословно и прикрепить результаты к словам?
Третий процесс делает то же самое, за исключением согласных.
И второй, и третий процесс используют один и тот же конвейер для отправки измененных слов четвертому процессу, который распечатает изменение в файл с именем output.dat .
После каждого процесса чтения, записи или модификации процессы распечатывают свой pid вместе с тем, что они сделали с файлом с именем log.dat
Когда я запускаю программу, я получаю всевозможные ошибки, связанные с закрытием каналов или чтением из каналов. Я просматривал код много раз, но не мог понять, что могло вызвать ошибки.
Вот код:
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <sys/wait.h>
#include <ctype.h>
#include <stddef.h>
int str_count_in_chars(char *start, char *end, char *chars) {
int count = 0;
for (; start != end; count += !!strchr(chars, *(start++)));
return count;
}
void str_swap_in_chars(size_t str_len, char **str, char *chars) {
int front,back;
for ( front = 0, back = str_len - 1; front < back; front++) {
if (strchr(chars, (*str)[front])) {
for (; !strchr(chars, (*str)[back]); back--);
char tmp = (*str)[front];
(*str)[front] = (*str)[back];
(*str)[back--] = tmp;
}
}
}
char *file_to_str(FILE *fin,int n) {
int buf_len = 64;
char buf[buf_len];
char *str = malloc(buf_len);
str[0] = '\0';
int i;
for (i = 1; i <= n; i++) {
fgets(buf, buf_len, fin);
if (!(str = realloc(str, i * buf_len))) {
fprintf(stderr, "%s:%d realloc failed\n", __FILE__, __LINE__);
exit(1);
}
strcat(str, buf);
}
return str;
}
int main(int argc, char *argv[]){
int pfd[2],pfd1[2],pfd2[2];
FILE *f =fopen("log.dat","w");
if(argc<2)
{
printf("Usage:\n%s <number>\n",argv[0]);
exit(1);
}
char *p=argv[1];
while(*p != '\0')
{
if(*p<'0' || *p>'9')
{
printf("%s is not a number!\n",argv[1]);
exit(1);
}
p++;
}
int n = atoi(argv[1]);
FILE *g;
if(pipe(pfd) == -1)
{
printf("Error opening first pipe\n");
exit(1);
}
if(pipe(pfd1) == -1)
{
printf("Error opening second pipe\n");
exit(1);
}
if(pipe(pfd2) == -1)
{
printf("Error opening third pipe\n");
exit(1);
}
/*child1*/
switch(fork())
{
case -1:
printf("Error forking child1!\n");
exit(1);
case 0:
/*closing unnecessary pipe ends*/
if(close(pfd[1]) == -1)
{
printf("Error closing writing end of first pipe\n");
exit(1);
}
if(close(pfd1[0]) == -1)
{
printf("Error closing reading end of second pipe\n");
exit(1);
}
if(close(pfd1[1]) == -1)
{
printf("Error closing writing end of second pipe\n");
exit(1);
}
if(close(pfd2[0]) == -1)
{
printf("Error closing reading end of third pipe\n");
exit(1);
}
/*reading from first pipe*/
char *words1=" ";
ssize_t numRead;
numRead=read(pfd[0],words1,strlen(words1));
if(numRead == -1);
{
printf("Error reading from first pipe\n");
exit(1);
}
fprintf(f,"First child pid_%d received data from parent pid_%d\n",getpid(),getppid());
fflush(f);
/*closing reading end of first pipe*/
if(close(pfd[0]) == -1)
{
printf("Error closing reading end of first pipr\n");
exit(1);
}
/*counting vowels from received words*/
/*if even, swapping them in pairs*/
/*concatenating each word with the number of vowels*/
char *vowels = "aeiou";
int i;
char *words2=" ";
for(i = 0; i < strlen(words1); )
{
if(isspace(words1[i]))
{
sprintf(words2,"%s",words1[i++]);
continue;
}
int start = i;
for (; i < strlen(words1) && !isspace(words1[i]); i++);
char *word = words1 + start;
int word_len = i - start;
int vowel_count = str_count_in_chars(word, words1 + i, vowels);
if (vowel_count % 2 == 0) {
str_swap_in_chars(word_len, &word, vowels);
}
sprintf(words2,"%.*s_%dvow",word_len,word,vowel_count);
}
fprintf(f,"First child pid_%d made the needed modifications\n",getpid());
fflush(f);
/*sending the words to third child*/
ssize_t stat;
stat=write(pfd2[1],words2,strlen(words2));
if(stat<0)
{
printf("Error writing to third pipe!\n");
exit(1);
}
fprintf(f,"First child pid_%d sent the modified data to third child",getpid());
fflush(f);
/*closing writing end of third pipe*/
if(close(pfd2[1]) == -1)
{
printf("Error closing writing end of third pipe\n");
exit(1);
}
default:
break;
}
/*child2*/
switch(fork())
{
case -1:
printf("Error forking child1!\n");
exit(1);
case 0:
/*closing unnecessary pipe ends*/
if(close(pfd[0]) == -1)
{
printf("Error closing reading end of first pipe\n");
exit(1);
}
if(close(pfd[1]) == -1)
{
printf("Error closing writing end of first pipe\n");
exit(1);
}
if(close(pfd1[1]) == -1)
{
printf("Error closing writing end of second pipe\n");
exit(1);
}
if(close(pfd2[0]) == -1)
{
printf("Error closing reading end of third pipe\n");
exit(1);
}
/*reading from second pipe*/
char *words3=" ";
ssize_t numRead;
numRead=read(pfd1[0],words3,strlen(words3));
if(numRead == -1)
{
printf("Error reading from second pipe\n");
exit(1);
}
fprintf(f,"Second child pid_%d received data from parent pid_%d\n",getpid(),getppid());
fflush(f);
/*closing reading end of second pipe*/
if(close(pfd1[0]) == -1)
{
printf("Error closing reading end of second pipe\n");
exit(1);
}
/*counting consonants from received words*/
/*if even, swapping them in pairs*/
/*concatenating each word with the number of consonants*/
char *cons = "qwrtypsdfghjklzxcvbnm";
int i;
char *words4=" ";
for(i = 0; i < strlen(words3); )
{
if(isspace(words3[i]))
{
sprintf(words4,"%s",words3[i++]);
continue;
}
int start = i;
for (; i < strlen(words3) && !isspace(words3[i]); i++);
char *word = words3 + start;
int word_len = i - start;
int cons_count = str_count_in_chars(word, words3 + i, cons);
if (cons_count % 2 == 0) {
str_swap_in_chars(word_len, &word, cons);
}
sprintf(words4,"%.*s_%dvow",word_len,word,cons_count);
}
fprintf(f,"Second child pid_%d made the needed modifications\n",getpid());
fflush(f);
/*sending the words to third child*/
ssize_t stat;
stat=write(pfd2[1],words4,strlen(words4));
if(stat<0)
{
printf("Error writing to third pipe!\n");
exit(1);
}
fprintf(f,"Second child pid_%d sent the modified data to third child",getpid());
fflush(f);
/*closing writing end of third pipe*/
if(close(pfd2[1]) == -1)
{
printf("Error closing writing end of third pipe\n");
exit(1);
}
default:
break;
}
/*child3*/
switch(fork())
{
case -1:
printf("Error forking child1!\n");
exit(1);
case 0:
/*closing unnecessary pipe ends*/
if(close(pfd[0]) == -1)
{
printf("Error closing reading end of first pipe\n");
exit(1);
}
if(close(pfd[1]) == -1)
{
printf("Error closing writing end of first pipe\n");
exit(1);
}
if(close(pfd1[1]) == -1)
{
printf("Error closing writing end of second pipe\n");
exit(1);
}
if(close(pfd1[0]) == -1)
{
printf("Error closing reading end of second pipe\n");
exit(1);
}
if(close(pfd2[1]) == -1)
{
printf("Error closing writing end of third pipe\n");
exit(1);
}
/*reading from third pipe*/
char *words5=" ";
FILE *h = fopen("output.dat","w");
ssize_t numRead;
numRead=read(pfd2[0],words5,strlen(words5));
if(numRead == -1)
{
printf("Error reading from third pipe\n");
exit(1);
}
fprintf(f,"Third child pid_%d received data\n",getpid());
fflush(f);
/*closing reading end of third pipe*/
if(close(pfd2[0]) == -1)
{
printf("Error closing reading end of third pipe\n");
exit(1);
}
/*printing received content to file*/
if(h)
{
fputs(words5,h);
}
else { printf("Failed to open file\n");}
fclose(h);
fprintf(f,"Third child pid_%d printed data to file\n",getpid());
fflush(f);
default:
break;
}
/*parent*/
if(close(pfd[0]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
if(close(pfd1[0]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
if(close(pfd2[0]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
if(close(pfd2[1]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
g = fopen("input.dat","r");
/*reading n words from file and sending it to child1 and child2*/
char *words = file_to_str(g,n);
printf("%s\n",words);
int words_len = strlen(words);
ssize_t stat;
stat=write(pfd[1],words,words_len);
if(stat<0)
{
printf("Error writing to first pipe!\n");
exit(1);
}
if(close(pfd[1]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
fprintf(f,"parent pid_%d sent data to child1\n",getpid());
fflush(f);
stat=write(pfd1[1],words,words_len);
if(stat<0)
{
printf("Error writing to second pipe!\n");
exit(1);
}
fprintf(f,"parent pid_%d sent data to child2\n",getpid());
fflush(f);
fclose(g);
if(close(pfd1[1]) == -1)
{
printf("Error closing reading end of the pipe.\n");
exit(EXIT_FAILURE);
}
fclose(f);
wait(NULL);
return 0;
}
Буду признателен за любое предложение.
РЕДАКТИРОВАТЬ
После внесения некоторых изменений в код с помощью отладчика программа по-прежнему не работает. Когда я запускаю программу, я получаю следующие ошибки:
-bash-4.1$ gcc program.c -o p
-bash-4.1$ ./p 4
Error reding from first pipe
Error reading from second pipe
Error closing reading end of the pipe.
И содержимое файла log.dat следующее:
-bash-4.1$ more log.dat
parent pid_61202 sent data to child1
parent pid_61202 sent data to child2
Third child pid_61205 received data
Third child pid_61205 printed data to file