C 程序中的命名管道 (unix)

Named pipes in C program (unix)

我必须使用3个进程才能解决这个问题。 第一个进程从(通过键盘输入)获取输入并将其发送到第二个进程 第二个过程将文本中的所有人声替换为 12345(a 替换为 1,e 替换为 2,...)。我得到了一个运行良好的 sh 脚本(对其进行了测试),它使用 sed 来完成这项任务。我会把它放在这里。 第三个过程仅在屏幕上输出字母数字行。我还有一个脚本,它使用 grep 来完成这个任务并且也工作正常(测试过)。 这个进程应该通过一个命名管道(一个 FIFO 文件)进行通信,我 运行 在通过 FIFO 发送和接收数据时遇到了一些困难。当我使用写入功能将数据写入 FIFO 时,它会在屏幕上输出数据,而当我在第二个进程中并尝试从 FIFO 读取数据时,它只是等待我输入的新输入。

第一个过程:

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

int main() {
    char text[500];  // buffer for the inputed text
    char aux[100];  // Also a buffer to save multi-line input into text buffer

    char* myfifo = "myfifo";
    int fd_text;  

    printf("\nInput: (to stop giving input just type 0 on a new line):\n");
    // Forming the text
    while(scanf("%[^\n]%*c", aux) == 1) {
        if(strcmp(aux, "0") == 0) 
            break;
        strcat(aux, "\n");
        strcat(text, aux);
        }
    strcat(text, "[=10=]");
    // Everything works well reading the input 


    int returnValue = mkfifo(myfifo, 0666);
    if(returnValue < 0) {
        printf("mkfifo() failed\nerrno = %d\n", errno);
        if(errno == EEXIST) 
            printf("That file already exists.\n");
    }

    if(fd_text = open(myfifo, O_WRONLY) < 0) {
        printf("error while opening FIFO");
        exit(0);
    } 

    int indicator = write(fd_text, text, strlen(text) + 1);
    if(indicator == 0) {
        printf("error while writing to FIFO");
    }

    close(fd_text);
    return 0;
}

第二个过程:

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

int main() {
    char text[500];  
    char* myfifo = "myfifo";

    int fd_text2;  

    if (fd_text2 = open(myfifo, O_RDONLY) < 0) {
        printf("error while opening FIFO");
        exit(1);
    }

    int result = read(fd_text2, text, 500);
    if (result < 0)
        printf("ERROR WHILE READING FROM THE FILE\n");
    printf("\n%d bytes were read from the file\n", result);
    printf("\nText read from FIFO:\n%s\n", text);

    // Saving the text into a txt to perfom the sed command on it
    FILE *fp_replace_text;
    fp_replace_text = fopen("replace_text.txt", "w");
    fprintf(fp_replace_text, "%s", text);
    fclose(fp_replace_text);

    system("chmod 777 replace.sh"); 
    system("./replace.sh replace_text.txt");  

    close(fd_text2);
    unlink(myfifo);
    return 0;
}

replace.sh

#!/bin/sh

sed -i 's/a/1/gi' 
sed -i 's/e/2/gi' 
sed -i 's/i/3/gi' 
sed -i 's/o/4/gi' 
sed -i 's/u/5/gi' 

如果我能弄清楚为什么进程 1 和进程 2 之间的通信不起作用,那么进程 3 将是相同的,所以我不再发布它了。

编辑:

第二个过程

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

int main() {
    char text[500]; 
    char* myfifo = "myfifo";
    int fd_text2; 

    if ((fd_text2 = open(myfifo, O_RDWR)) < 0) {
        printf("error while opening pipe");
        exit(1);
    }

    int result = read(fd_text2, text, 500);
    if (result < 0)
        printf("ERROR WHILE READING FROM THE FILE\n");


    FILE *fp_replace_text;
    fp_replace_text = fopen("replace_text.txt", "w");
    fprintf(fp_replace_text, "%s", text);
    fclose(fp_replace_text);

    system("chmod 777 replace.sh");  
    system("./replace.sh replace_text.txt");  

    fp_replace_text = fopen("replace_text.txt", "r");
    fread(text, 500, 1, fp_replace_text);
    fclose(fp_replace_text);

    write(fd_text2, text, strlen(text) + 1);    
    close(fd_text2);
    return 0;
}

第三道工序

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

int main() {
    char text[500];  
    char* myfifo = "myfifo";
    int fd_text3;  

    if ((fd_text3 = open(myfifo, O_RDONLY)) < 0) {
        printf("error while opening pipe");
        exit(1);
    }

    int result = read(fd_text3, text, 500);
    if (result < 0)
        printf("ERROR WHILE READING FROM THE FILE\n");

    FILE *fp_replace_text;
    fp_replace_text = fopen("replace_text.txt", "r");
    fread(text, 500, 1, fp_replace_text);
    fclose(fp_replace_text);

    printf("Textul final este:\n");
    system("chmod 777 output.sh");
    system("./output.sh replace_text.txt"); 

    unlink(myfifo);
    return 0;
}

我也在尝试通过 FIFO 将 txt 文件的内容发送到第三个进程(我知道我可以只使用 txt 文件,但我想使用 FIFO 文件并再次从中读取)。所以我在 txt 文件上使用 shell 脚本,我从中读取然后我想将从 txt 文件读取的内容发送到第三个进程到 FIFO,但是在我 运行 之后第二个进程执行停止并且不阻塞。当我在第一个进程中写入 FIFO 时,它会阻塞,直到第二个进程从 FIFO 读取数据。第二个进程继续执行,第三个进程什么也得不到。我想 FIFO 原则一定有问题,如果你想在 FIFO 上执行 input/output 操作,两端都应该打开。

问题(应该引起编译器的警告)是在这样的语句中:

if(fd_text = open(myfifo, O_WRONLY) < 0)

您似乎假设这将从左到右进行评估,首先为 fd_text 赋值,然后根据 0 测试该值以给出一个布尔值,该值将决定是否输入 if块。但在 C 中,关系 运算符(如 <)优先于 赋值 运算符(如 =)。所以首先我们将 open 命令的结果与 0 进行比较,然后将比较的布尔结果赋值给 fd_text。因此文件描述符丢失,进一步尝试到达 fifo 将失败。我们可以用一对括号来纠正这个问题:

if((fd_text = open(myfifo, O_WRONLY)) < 0)

更一般地说,尽可能独立开发新功能是个好主意。如果你想将文本发送到 fifo 并接收它,只需在第一个模块中硬编码一些文本,不需要所有的代码来读取用户输入,并且不要尝试从 fifo 发送文本的进一步步骤第二个模块到其他一些修改过程,直到 fifo 工作正常。小步骤。