C - 并行写入和读取 FIFO 文件 - 意外行为

标签 c pipe fifo

我有两个管道连接到 FIFO 文件,读取器和写入器。我打开两个终端并在 writer 上写,并期望文本出现在 reader 上。出于某种原因,我遇到了非常奇怪的行为 - 有时会添加一个空格或一些字符,我不知道为什么。有人能帮我吗? 我附上阅读器和编写器代码。

读者:

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

#define BUF_SIZE 1024

struct sigaction sigHelp;
struct sigaction intAct;
struct sigaction termAct;
struct stat st;
int line;
char buf[BUF_SIZE];
int main(int argc, char* argv[]) {
    char *filePath = argv[1];
    assert (argc == 2);
    sigHelp.sa_handler = SIG_IGN;
    sigHelp.sa_flags = 0;
    sigemptyset(&intAct.sa_mask);
    while(1) {
        int indicator = 1;
        while(indicator) {
            int statErr = stat(filePath, &st);
            if (statErr == 0) {
                if (!S_ISFIFO(st.st_mode)) {
                    printf("Error: file is not a FIFO file.\n");
                }
                else {
                    indicator = 0;
                    break;
                }
            }
            else {
                if (errno == ENOENT) { //wait for file
                    sleep(1);
                }
                else {
                    printf("Error checking file status - %s\n", strerror(errno));
                    return -1;
                }
            }
        }
        int intErr = sigaction(SIGINT, &sigHelp, &intAct);
        if(intErr == -1) {
            printf("Error: sigint action failed - %s\n" ,strerror(errno));
            return -1;
        }
        int termErr = sigaction(SIGTERM, &sigHelp, &termAct);
        if(termErr == -1) {
            printf("Error: sigterm action failed - %s\n" ,strerror(errno));
            return -1;
        }
        line = open(filePath, O_RDONLY, S_IRWXU|S_IRWXG|S_IRWXO);
        assert(line != -1);
        while (1) {
            int readInd = read(line, buf, BUF_SIZE);
            if(readInd == -1){
                printf("Error: failed reading from FIFO file - %s\n", strerror(errno));
                close(line);
            }
            else if(readInd == 0) {
                break;
            }
            printf("%s ", buf);
        }
        close(line);
        int intE = sigaction(SIGINT, &intAct, NULL);
        if(intE == -1){
            printf("Error: sigint action failed - %s\n" ,strerror(errno));
            return -1;
        }
        int termE = sigaction(SIGTERM, &termAct, NULL);
        if(termE == -1){
            printf("Error: sigterm action failed - %s\n" ,strerror(errno));
            return -1;
        }
    }   
    return 0;
}

作者:

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

#define LINE_SIZE 1024

struct sigaction sigAct;
const char* fileName;
int fifoFile;
int warnIndicator = 0;
struct stat st; 
mode_t mode;
void handle_signal(int signal);
int main(int argc, char *argv[]){
    assert(argc == 2);
    fileName = argv[1];
    sigAct.sa_handler = &handle_signal; //opinter to function
    int si = sigaction(SIGINT, &sigAct, NULL); 
    if (si < 0) {
        printf("Error: sigint action failed - %s\n",strerror(errno));
        return -1;
    }
    int stin = sigaction(SIGTERM, &sigAct, NULL);
    if (stin < 0) {
        printf("Error: sigterm action failed - %s\n",strerror(errno));
        return -1;
    }
    int sp = sigaction(SIGPIPE, &sigAct, NULL);
    if (sp < 0) {
        printf("Error: sigpipe action failed - %s\n",strerror(errno));
        return -1;
    }
    mode = ACCESSPERMS;
    int statSuc = stat(argv[1], &st);
    if (statSuc == -1) {
        if (errno != ENOENT) {
            printf("Error: stat failed - %s\n", strerror(errno));
            return -1;
        }
    }
    else { // stat success
        int fifoInd = S_ISFIFO(st.st_mode);
        if (fifoInd != 0) {
            fifoFile =  open(argv[1], O_WRONLY, mode);
        }
        else {
            int linkInd = unlink(argv[1]);
            if (linkInd == -1) {
                printf( "Error: unlink failed - %s\n", strerror(errno));
                return -1;
            }
        }
    }
    int fifoInd = mkfifo(argv[1], mode);
    if (fifoInd == -1) {
        printf("Error: making fifo failed - %s\n", strerror(errno));
        return -1;
    }
    fifoFile =  open(argv[1], O_WRONLY, mode);
    char line[LINE_SIZE];
    while (fgets(line, LINE_SIZE, stdin) != NULL) {
        write (fifoFile,line,strlen(line));
    }
    int unlinkSuc = unlink(argv[1]);
    if (unlinkSuc == -1) {
        printf( "Error: unlink failed - %s\n", strerror( errno ) );
        return -1;
    }
    close(fifoFile);
    return 0;
}
void handle_signal(int sign) { 
    if (sign == SIGPIPE || sign == SIGINT || sign == SIGTERM) {
        if (sign == SIGPIPE) {
            if (warnIndicator == 0) {
                printf("Error: writing to closed pipe \n");
                warnIndicator == 1;
            }
        }
        else {
            unlink(fileName);
            close(fifoFile);
            exit(1);
        }
    }
}

谢谢,如果时间太长,我们深表歉意。

最佳答案

write(fifoFile, line, strlen(line));

这不是写入读者期望的终止 NUL 字节(因为读者将其视为字符串)。更改为:

write(fifoFile, line, strlen(line) + 1); 

关于C - 并行写入和读取 FIFO 文件 - 意外行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34122528/

相关文章:

C 程序因某些输入而突然结束

c - 我如何处理 CS50 首字母中单词之前或之间的多个空格(更舒适)?

使用 malloc 和 realloc 将静态数组更改为动态数组?

c++ - 用 dup 管道传输后如何取回标准输出?

git - 如何通过管道传输到 git tag 命令?

amazon-web-services - 至少传送一次的 SQS 消息所占的百分比是多少?

java - 通过删除 PRIME ASCII 字符来打印字符串

php - 在 php 中使用 pdftopm 将 pdf 转换为图像,而无需在磁盘上写入文件

fifo - KDB:先进先出方式的pnl

amazon-web-services - AWS SQS : Which is the order of message in a FIFO queue after visibility-timeout expires?