Можем ли мы выполнить операцию, используя такие функции, как fgets (), fputs (), feof () и т. д. для файла fifo, который мы используем для обычного файла? - PullRequest
0 голосов
/ 08 ноября 2019

У меня есть задание, в котором я должен передать файл из процесса клиента в процесс сервера с использованием fifo. Я пытался работать с файлом fifo как с другими файлами, которые мы создаем в системе. Он скомпилирован без каких-либо ошибок, но не работает должным образом. Может кто-нибудь дать мне представление о структуре файлов fifo внутри компьютерной системы? Какие процессы и функции для него присутствуют? До сих пор я знаю, как использовать функции create (), read (), write (), open () для файла fifo. Также я был бы признателен, если бы кто-то мог помочь мне исправитьмоя программа?

Моя клиентская и серверная программы: -

Клиентская программа: -

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

int main()
{
int fd;
char *myfifo ="/tmp/myfifo";
char str[80];
FILE *fp;
char filename[20];
printf("\nEnter filename: ");
gets(filename);
mkfifo(myfifo,0666);
fp = fopen(filename,"r");
if(fp == NULL)
{
   printf("\nError opening the file");
   exit(1);
}
fd = open(myfifo, O_WRONLY);
while(fgets(str,80,fp)!=NULL)
{
  write(fd,str,strlen(str)+1);
}
close(fd);
fclose(fp);
return 0;
}

Клиентская программа: -

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

int main()
{
    int fd1;
    char *myfifo ="/tmp/myfifo";
    char str1[80], filename[20];

    FILE *fp1, *fp2;
    fd1= open(myfifo, O_RDONLY);
    fp1 = fopen(filename,"r");
    fp2 = fopen(filename,"w");
    while(!feof(fp1))
    {
        read(fd1,str1,strlen(str1)+1);
        fputs(str1,fp2);
    }
     return 0;



   }

1 Ответ

2 голосов
/ 08 ноября 2019

Да, но у вас есть несколько небольших проблем в ваших программах. в первом:

write(fd, str, strlen(str)+1);

немного нетрадиционно. Это отправляет строку плюс ее разделитель конца строки (\ 0) в fd. Обычно это не делается со строками, strlen (str), вероятно, то, что вы хотите.

во втором:

fp1 = fopen(filename,"r");
fp2 = fopen(filename,"w");

имени файла не было присвоено значение, поэтому оба изэти открытия почти наверняка потерпят неудачу. Когда они это делают, они возвращают NULL-указатель, поэтому первая попытка использовать их:

while (! Feof (fp1))

, скорее всего, вызовет нарушение сегмента. Кроме того, вы в любом случае не используете fp1, поэтому, если feof (fp1) вернул 1, он всегда вернет 1. Вы хотите, чтобы этот цикл основывался на исчерпании fifo, что означает, что в нем нет данных, и никто не имеетэто открыто для записи. Таким образом, немного изменив эту программу, вы получите:

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

int main()
{
    int fd1;
    char *myfifo ="/tmp/myfifo";
    char str1[80];
    ssize_t n;
    fd1= open(myfifo, O_RDONLY);
    while ((n=read(fd1,str1,sizeof str1)) > 0)
    {
        fwrite(str1, 1, n, stdout);
    }
    return 0;
}

Хотя этот набор изменений работает, он не решает другой вопрос об использовании функций stdio с конвейерами. Ответ - да, и вот еще одна функциональная перезапись вашей второй программы:

#include<stdio.h>

int main()
{
    char *myfifo ="/tmp/myfifo";
    FILE *fp;
    int c;
    if ((fp = fopen(myfifo, "r")) != NULL) {
    while ((c = getc(fp)) != EOF) {
        putchar(c);
    }
    fclose(fp);
    }
    return 0;
}

Кроме того, в первом критический бит с stdio:

...
FILE *fi = fopen(myfifo, "a");
while(fgets(str,80,fp)!=NULL)
{
  fputs(str, fi);
}
fclose(fi);
...

, как во второй, цикл мог быть реализован с помощью getc, putc. Общее уточнение может быть такими функциями:

ssize_t FCopy(FILE *in, FILE *out) {
    int c;
    ssize_t len = 0;
    while ((c = getc(in)) != EOF) {
        len++;
        if (putc(c, out) != c) {
            return -len;
        }
    }
    return len;
}
ssize_t FileAppend(char *from, char *to) {
    FILE *in, *out;
    ssize_t n = 0;
    if ((in = fopen(from, "rb")) != NULL) {
        if ((out = fopen(to, "ab")) != NULL) {
            n = FCopy(in, out);
            fclose(out);
        } else {
            n = -1;
        }
        fclose(in);
    } else {
        n = -1;
    }
    return n;
}

, поэтому ваш основной файл будет выглядеть примерно так:

...
   char filename[80];
   printf("Enter a file to store the data in: ");
   if (fgets(filename, sizeof filename, stdin)) {
       filename[strlen(filename)-1] = '\0';
       if (FileAppend(myfifo, filename) < 0) {
           printf("Error: could not save data to %s\n", filename);
       }
   }
....
...